library(coda)
library(bayesplot) 
library(ggplot2)
library(ggsci)
library(khroma)
library(tidyverse)
library(reshape2)
library(here)
knitr::opts_chunk$set(echo = TRUE, dpi = 300 )

Set up MCSim file

# this markdown file must be saved in top level directory for the following to work; the mcsim code depends on getwd results.
mdir <- "MCSim"
source(here::here(mdir,"setup_MCSim.R"))
# Make mod.exe (used to create mcsim executable from model file)
makemod() 
The mod.exe had been created.

Set filenames and load data

Set up dataset

id_lut <- multicheck$df_check %>% select(Level) %>% unique ()  %>%
  mutate(dataset = c( 
    rep("Decatur M Train", 9),
    rep("Decatur F Train", 9),
    rep("Decatur M Test", 9),
    rep("Decatur F Test", 10),
    'Paulsboro-Train','Horsham-Train',
    'Warminster-Test'), 
    Sex = c( 
    rep("M", 9),
    rep("F", 9),
    rep("M", 9),
    rep("F", 10),
    'Mixed', 'Mixed',  'Mixed'),
    City = c( 
    rep("Decatur", 18),
    rep("Decatur", 19),
    'Paulsboro','Horsham','Warminster'), 
    Train_Test = c( 
    rep("Train", 9),
    rep("Train", 9),
    rep("Test", 9),
    rep("Test", 10),
    'Train',  'Train', 'Test'),
    datatype = c(
      rep("Individual",9+9+9+10),
      rep("Summary",3)),
    Simulation = row_number(),
    variable = paste0(dataset, " ",Simulation))

id_lut$dataset <- factor(id_lut$dataset,levels=
                           c("Decatur M Train","Decatur F Train","Arnsberg M Train",
                             "Arnsberg F Train","Decatur M Test","Decatur F Test","Arnsberg M Test",
                             "Arnsberg F Test","Minnesota Train","Minnesota Test",
                             'Lubeck-Bartell-Train', 'Lubeck-Bartell-Test',
                             'Little Hocking-Bartell-Train', 'Little Hocking-Bartell-Test',
                             'Little Hocking-Emmett-Test','Paulsboro-Train','Horsham-Train',
                             'Warminster-Test','Warrington-Train'))
id_lut$City <- factor(id_lut$City,levels = 
                        c("Decatur","Arnsberg","Minnesota",'Lubeck-Bartell',
                          'Little Hocking-Bartell','Little Hocking-Emmett',
                          'Paulsboro','Horsham','Warminster','Warrington'))
 
indiv_lut <- id_lut %>% 
  filter(City %in% c("Decatur")) %>%
  mutate(  dataset = as.factor(dataset))

nv <- data.frame(dataset =unique(indiv_lut$dataset), 
           variable= rep("Pop GM", 4),
           type= rep("Pop GM", 4), stringsAsFactors = FALSE)

Scatter plot of predictions (median of multicheck samples) versus data.

This is a Figure 2 panel. Needed to use “scale=1.1” in ggsave to match PFOA.

nrow(multicheck$df_check)
[1] 38500
nrow(id_lut)
[1] 40
multicheck$df_check %>% left_join(id_lut) %>% nrow()
Joining, by = c("Level", "Simulation")
[1] 38500
names(multicheck$df_check)
[1] "Level"      "Simulation" "Output_Var" "Time"       "Data"      
[6] "Prediction"
Level

Simulation

Output_Var

Time

Data

Prediction
multicheck2 <- multicheck$df_check %>% left_join(id_lut)%>% 
  group_by_at ( vars(-Prediction)) %>% 
  summarise(Prediction = median(Prediction)) %>%
  ungroup() %>%
  group_by(City) %>% 
  mutate(Train_Test = factor(Train_Test, levels = c("Train", "Test")),
         `City (datatype)` = factor (paste0(City, "\n(", datatype, ")\n") ),
         label = case_when(Train_Test=="Train" ~ "E: PFNA Train",
                           Train_Test=="Test"  ~ "F: PFNA Test",
                           TRUE ~ ""))
Joining, by = c("Level", "Simulation")
Warning in mutate_impl(.data, dots, caller_env()): Unequal factor levels:
coercing to character
Warning in mutate_impl(.data, dots, caller_env()): binding character and factor
vector, coercing into character vector

Warning in mutate_impl(.data, dots, caller_env()): binding character and factor
vector, coercing into character vector

Warning in mutate_impl(.data, dots, caller_env()): binding character and factor
vector, coercing into character vector

Warning in mutate_impl(.data, dots, caller_env()): binding character and factor
vector, coercing into character vector
 #define color for testing boxplots
bp_cols <- c (as.character (khroma::colour("muted")(9)) , "#191919")   
bp_cols <-bp_cols[c(1, 7, 9:8)]# plot_scheme_colourblind(bp_cols) 

### Create aesthetics lookup
aes_lut <- multicheck2 %>% ungroup() %>% 
  group_by(City, datatype,  `City (datatype)` ) %>% summarise () %>% ungroup() %>%
  mutate( cols = bp_cols, city_fills =   bp_cols , 
          # for individual level on point plot (multicheck2), darken outlines for visibility, use standard colors otherwise
         city_outlines =  if_else(datatype == "Individual"  ,  colorspace::darken(city_fills, 0.3), city_fills) ,  
         shapes = case_when(datatype == "Individual"  & `City` %in% c('Decatur', 'Arnsberg', 'Minnesota')   ~  23,
                            datatype == "Summary" &`City` %in% c("Horsham", "Warminster",  "Warrington") ~ 2,
                            datatype == "Summary" & `City` == "Paulsboro" ~ 1,
                            TRUE ~ 18                                ), 
         size = if_else(datatype =="Individual", 1.75, 2.5 ) )  



source( paste0(gsub(basename(here()), 'shared_functions', here()), '/plot_scatter_mcheck.r'))

p2 <- plot_scatter_mcheck(dframe = multicheck2, pfas_nom = pfas_name, aes_lut_fn = aes_lut )
print(p2) 

ggsave(here ("output-plots", paste0( sa,"multicheckplot_", pfas_name,
               ".pdf")),p2,dpi=600, scale=1.1)
Saving 8.8 x 3.85 in image

Parse multicheck

df_check <- multicheck$df_check
df_check <- subset(df_check,Data > 0) 

n1 <- nrow(df_check)
id_chks <- df_check %>% select(Level) %>% unique() %>% bind_cols(id_lut)  %>%
  mutate(dataset = as.factor(dataset), Sex = as.factor(Sex), City = as.factor(City), 
         Train_Test = as.factor(Train_Test))

df_check <- df_check %>% left_join(id_chks, by = "Simulation")%>%
  mutate(Dataset = paste(as.character(dataset), Simulation),
         Sex = ordered(Sex, levels = c("M", "F", "Mixed"), 
                       labels = c("Male", "Female", "Mixed (all sexes)")))
n2 <- nrow(df_check)
if(n1 != n2)print("duplicates created in id-lut join")
df_check$Time.desc <- as.character(paste0("T=",df_check$Time))
df_check$Time.desc[df_check$Time.desc == "T=1e-06"] <- "SteadyState"
df_check$Dataset.Time <- interaction(df_check$Dataset,
                                     df_check$Time.desc,lex.order=TRUE)
df_check$Dataset.Time <- factor(df_check$Dataset.Time,
                                levels=levels(df_check$Dataset.Time))
calibdata <- df_check[,names(df_check) != "Prediction"]
calibdata <- calibdata[!duplicated(calibdata),]
print(calibdata)
      Level.x Simulation Output_Var  Time  Data    Level.y     Level1
1   1_1_1_1_1          1     Cserum 0.000 1.900  1_1_1_1_1  1_1_1_1_1
2   1_1_1_1_1          1     Cserum 5.802 1.100  1_1_1_1_1  1_1_1_1_1
3   1_1_1_1_2          2     Cserum 0.000 1.100  1_1_1_1_2  1_1_1_1_2
4   1_1_1_1_2          2     Cserum 5.802 0.900  1_1_1_1_2  1_1_1_1_2
5   1_1_1_1_3          3     Cserum 0.000 2.100  1_1_1_1_3  1_1_1_1_3
6   1_1_1_1_3          3     Cserum 5.802 0.700  1_1_1_1_3  1_1_1_1_3
7   1_1_1_1_4          4     Cserum 0.000 1.900  1_1_1_1_4  1_1_1_1_4
8   1_1_1_1_4          4     Cserum 5.802 0.500  1_1_1_1_4  1_1_1_1_4
9   1_1_1_1_5          5     Cserum 0.000 3.500  1_1_1_1_5  1_1_1_1_5
10  1_1_1_1_5          5     Cserum 5.802 0.900  1_1_1_1_5  1_1_1_1_5
11  1_1_1_1_6          6     Cserum 0.000 1.200  1_1_1_1_6  1_1_1_1_6
12  1_1_1_1_6          6     Cserum 5.802 0.600  1_1_1_1_6  1_1_1_1_6
13  1_1_1_1_7          7     Cserum 0.000 2.700  1_1_1_1_7  1_1_1_1_7
14  1_1_1_1_7          7     Cserum 5.802 0.800  1_1_1_1_7  1_1_1_1_7
15  1_1_1_1_8          8     Cserum 0.000 1.700  1_1_1_1_8  1_1_1_1_8
16  1_1_1_1_8          8     Cserum 5.802 0.500  1_1_1_1_8  1_1_1_1_8
17  1_1_1_1_9          9     Cserum 0.000 1.100  1_1_1_1_9  1_1_1_1_9
18  1_1_1_1_9          9     Cserum 5.802 0.600  1_1_1_1_9  1_1_1_1_9
19 1_1_1_1_10         10     Cserum 0.000 1.600 1_1_1_1_10 1_1_1_1_10
20 1_1_1_1_10         10     Cserum 5.802 1.000 1_1_1_1_10 1_1_1_1_10
21 1_1_1_1_11         11     Cserum 0.000 2.000 1_1_1_1_11 1_1_1_1_11
22 1_1_1_1_11         11     Cserum 5.802 1.100 1_1_1_1_11 1_1_1_1_11
23 1_1_1_1_12         12     Cserum 0.000 1.000 1_1_1_1_12 1_1_1_1_12
24 1_1_1_1_12         12     Cserum 5.802 0.400 1_1_1_1_12 1_1_1_1_12
25 1_1_1_1_13         13     Cserum 0.000 1.700 1_1_1_1_13 1_1_1_1_13
26 1_1_1_1_13         13     Cserum 5.802 0.400 1_1_1_1_13 1_1_1_1_13
27 1_1_1_1_14         14     Cserum 0.000 3.900 1_1_1_1_14 1_1_1_1_14
28 1_1_1_1_14         14     Cserum 5.802 1.200 1_1_1_1_14 1_1_1_1_14
29 1_1_1_1_15         15     Cserum 0.000 2.400 1_1_1_1_15 1_1_1_1_15
30 1_1_1_1_15         15     Cserum 5.802 3.600 1_1_1_1_15 1_1_1_1_15
31 1_1_1_1_16         16     Cserum 0.000 1.200 1_1_1_1_16 1_1_1_1_16
32 1_1_1_1_16         16     Cserum 5.802 0.600 1_1_1_1_16 1_1_1_1_16
33 1_1_1_1_17         17     Cserum 0.000 2.900 1_1_1_1_17 1_1_1_1_17
34 1_1_1_1_17         17     Cserum 5.802 0.900 1_1_1_1_17 1_1_1_1_17
35 1_1_1_1_18         18     Cserum 0.000 1.200 1_1_1_1_18 1_1_1_1_18
36 1_1_1_1_18         18     Cserum 5.802 0.400 1_1_1_1_18 1_1_1_1_18
37  1_1_1_2_1         19     Cserum 0.000 1.500  1_1_1_2_1  1_1_1_2_1
38  1_1_1_2_1         19     Cserum 5.802 0.400  1_1_1_2_1  1_1_1_2_1
39  1_1_1_2_2         20     Cserum 0.000 3.300  1_1_1_2_2  1_1_1_2_2
40  1_1_1_2_2         20     Cserum 5.802 1.000  1_1_1_2_2  1_1_1_2_2
41  1_1_1_2_3         21     Cserum 0.000 1.800  1_1_1_2_3  1_1_1_2_3
42  1_1_1_2_3         21     Cserum 5.802 0.600  1_1_1_2_3  1_1_1_2_3
43  1_1_1_2_4         22     Cserum 0.000 1.600  1_1_1_2_4  1_1_1_2_4
44  1_1_1_2_4         22     Cserum 5.802 0.700  1_1_1_2_4  1_1_1_2_4
45  1_1_1_2_5         23     Cserum 0.000 4.300  1_1_1_2_5  1_1_1_2_5
46  1_1_1_2_5         23     Cserum 5.802 1.400  1_1_1_2_5  1_1_1_2_5
47  1_1_1_2_6         24     Cserum 0.000 1.700  1_1_1_2_6  1_1_1_2_6
48  1_1_1_2_6         24     Cserum 5.802 1.400  1_1_1_2_6  1_1_1_2_6
49  1_1_1_2_7         25     Cserum 0.000 1.300  1_1_1_2_7  1_1_1_2_7
50  1_1_1_2_7         25     Cserum 5.802 0.400  1_1_1_2_7  1_1_1_2_7
51  1_1_1_2_8         26     Cserum 0.000 3.000  1_1_1_2_8  1_1_1_2_8
52  1_1_1_2_8         26     Cserum 5.802 1.000  1_1_1_2_8  1_1_1_2_8
53  1_1_1_2_9         27     Cserum 0.000 3.100  1_1_1_2_9  1_1_1_2_9
54  1_1_1_2_9         27     Cserum 5.802 1.300  1_1_1_2_9  1_1_1_2_9
55 1_1_1_2_10         28     Cserum 0.000 1.500 1_1_1_2_10 1_1_1_2_10
56 1_1_1_2_10         28     Cserum 5.802 1.200 1_1_1_2_10 1_1_1_2_10
57 1_1_1_2_11         29     Cserum 0.000 3.100 1_1_1_2_11 1_1_1_2_11
58 1_1_1_2_11         29     Cserum 5.802 1.900 1_1_1_2_11 1_1_1_2_11
59 1_1_1_2_12         30     Cserum 0.000 1.900 1_1_1_2_12 1_1_1_2_12
60 1_1_1_2_12         30     Cserum 5.802 0.800 1_1_1_2_12 1_1_1_2_12
61 1_1_1_2_13         31     Cserum 0.000 1.000 1_1_1_2_13 1_1_1_2_13
62 1_1_1_2_13         31     Cserum 5.802 1.100 1_1_1_2_13 1_1_1_2_13
63 1_1_1_2_14         32     Cserum 0.000 1.200 1_1_1_2_14 1_1_1_2_14
64 1_1_1_2_14         32     Cserum 5.802 0.400 1_1_1_2_14 1_1_1_2_14
65 1_1_1_2_15         33     Cserum 0.000 2.500 1_1_1_2_15 1_1_1_2_15
66 1_1_1_2_15         33     Cserum 5.802 0.900 1_1_1_2_15 1_1_1_2_15
67 1_1_1_2_16         34     Cserum 0.000 1.200 1_1_1_2_16 1_1_1_2_16
68 1_1_1_2_16         34     Cserum 5.802 0.400 1_1_1_2_16 1_1_1_2_16
69 1_1_1_2_17         35     Cserum 0.000 2.300 1_1_1_2_17 1_1_1_2_17
70 1_1_1_2_17         35     Cserum 5.802 0.700 1_1_1_2_17 1_1_1_2_17
71 1_1_1_2_18         36     Cserum 0.000 1.500 1_1_1_2_18 1_1_1_2_18
72 1_1_1_2_18         36     Cserum 5.802 0.500 1_1_1_2_18 1_1_1_2_18
73 1_1_1_2_19         37     Cserum 0.000 1.900 1_1_1_2_19 1_1_1_2_19
74 1_1_1_2_19         37     Cserum 5.802 1.100 1_1_1_2_19 1_1_1_2_19
75      1_2_1         38 M_Cbgd_Css 2.200 5.710      1_2_1      1_2_1
76      1_3_1         39 M_Cbgd_Css 2.000 0.925      1_3_1      1_3_1
77      1_4_1         40 M_Cbgd_Css 2.000 1.060      1_4_1      1_4_1
           dataset               Sex       City Train_Test   datatype
1  Decatur M Train              Male    Decatur      Train Individual
2  Decatur M Train              Male    Decatur      Train Individual
3  Decatur M Train              Male    Decatur      Train Individual
4  Decatur M Train              Male    Decatur      Train Individual
5  Decatur M Train              Male    Decatur      Train Individual
6  Decatur M Train              Male    Decatur      Train Individual
7  Decatur M Train              Male    Decatur      Train Individual
8  Decatur M Train              Male    Decatur      Train Individual
9  Decatur M Train              Male    Decatur      Train Individual
10 Decatur M Train              Male    Decatur      Train Individual
11 Decatur M Train              Male    Decatur      Train Individual
12 Decatur M Train              Male    Decatur      Train Individual
13 Decatur M Train              Male    Decatur      Train Individual
14 Decatur M Train              Male    Decatur      Train Individual
15 Decatur M Train              Male    Decatur      Train Individual
16 Decatur M Train              Male    Decatur      Train Individual
17 Decatur M Train              Male    Decatur      Train Individual
18 Decatur M Train              Male    Decatur      Train Individual
19 Decatur F Train            Female    Decatur      Train Individual
20 Decatur F Train            Female    Decatur      Train Individual
21 Decatur F Train            Female    Decatur      Train Individual
22 Decatur F Train            Female    Decatur      Train Individual
23 Decatur F Train            Female    Decatur      Train Individual
24 Decatur F Train            Female    Decatur      Train Individual
25 Decatur F Train            Female    Decatur      Train Individual
26 Decatur F Train            Female    Decatur      Train Individual
27 Decatur F Train            Female    Decatur      Train Individual
28 Decatur F Train            Female    Decatur      Train Individual
29 Decatur F Train            Female    Decatur      Train Individual
30 Decatur F Train            Female    Decatur      Train Individual
31 Decatur F Train            Female    Decatur      Train Individual
32 Decatur F Train            Female    Decatur      Train Individual
33 Decatur F Train            Female    Decatur      Train Individual
34 Decatur F Train            Female    Decatur      Train Individual
35 Decatur F Train            Female    Decatur      Train Individual
36 Decatur F Train            Female    Decatur      Train Individual
37  Decatur M Test              Male    Decatur       Test Individual
38  Decatur M Test              Male    Decatur       Test Individual
39  Decatur M Test              Male    Decatur       Test Individual
40  Decatur M Test              Male    Decatur       Test Individual
41  Decatur M Test              Male    Decatur       Test Individual
42  Decatur M Test              Male    Decatur       Test Individual
43  Decatur M Test              Male    Decatur       Test Individual
44  Decatur M Test              Male    Decatur       Test Individual
45  Decatur M Test              Male    Decatur       Test Individual
46  Decatur M Test              Male    Decatur       Test Individual
47  Decatur M Test              Male    Decatur       Test Individual
48  Decatur M Test              Male    Decatur       Test Individual
49  Decatur M Test              Male    Decatur       Test Individual
50  Decatur M Test              Male    Decatur       Test Individual
51  Decatur M Test              Male    Decatur       Test Individual
52  Decatur M Test              Male    Decatur       Test Individual
53  Decatur M Test              Male    Decatur       Test Individual
54  Decatur M Test              Male    Decatur       Test Individual
55  Decatur F Test            Female    Decatur       Test Individual
56  Decatur F Test            Female    Decatur       Test Individual
57  Decatur F Test            Female    Decatur       Test Individual
58  Decatur F Test            Female    Decatur       Test Individual
59  Decatur F Test            Female    Decatur       Test Individual
60  Decatur F Test            Female    Decatur       Test Individual
61  Decatur F Test            Female    Decatur       Test Individual
62  Decatur F Test            Female    Decatur       Test Individual
63  Decatur F Test            Female    Decatur       Test Individual
64  Decatur F Test            Female    Decatur       Test Individual
65  Decatur F Test            Female    Decatur       Test Individual
66  Decatur F Test            Female    Decatur       Test Individual
67  Decatur F Test            Female    Decatur       Test Individual
68  Decatur F Test            Female    Decatur       Test Individual
69  Decatur F Test            Female    Decatur       Test Individual
70  Decatur F Test            Female    Decatur       Test Individual
71  Decatur F Test            Female    Decatur       Test Individual
72  Decatur F Test            Female    Decatur       Test Individual
73  Decatur F Test            Female    Decatur       Test Individual
74  Decatur F Test            Female    Decatur       Test Individual
75 Paulsboro-Train Mixed (all sexes)  Paulsboro      Train    Summary
76   Horsham-Train Mixed (all sexes)    Horsham      Train    Summary
77 Warminster-Test Mixed (all sexes) Warminster       Test    Summary
             variable            Dataset Time.desc               Dataset.Time
1   Decatur M Train 1  Decatur M Train 1       T=0      Decatur M Train 1.T=0
2   Decatur M Train 1  Decatur M Train 1   T=5.802  Decatur M Train 1.T=5.802
3   Decatur M Train 2  Decatur M Train 2       T=0      Decatur M Train 2.T=0
4   Decatur M Train 2  Decatur M Train 2   T=5.802  Decatur M Train 2.T=5.802
5   Decatur M Train 3  Decatur M Train 3       T=0      Decatur M Train 3.T=0
6   Decatur M Train 3  Decatur M Train 3   T=5.802  Decatur M Train 3.T=5.802
7   Decatur M Train 4  Decatur M Train 4       T=0      Decatur M Train 4.T=0
8   Decatur M Train 4  Decatur M Train 4   T=5.802  Decatur M Train 4.T=5.802
9   Decatur M Train 5  Decatur M Train 5       T=0      Decatur M Train 5.T=0
10  Decatur M Train 5  Decatur M Train 5   T=5.802  Decatur M Train 5.T=5.802
11  Decatur M Train 6  Decatur M Train 6       T=0      Decatur M Train 6.T=0
12  Decatur M Train 6  Decatur M Train 6   T=5.802  Decatur M Train 6.T=5.802
13  Decatur M Train 7  Decatur M Train 7       T=0      Decatur M Train 7.T=0
14  Decatur M Train 7  Decatur M Train 7   T=5.802  Decatur M Train 7.T=5.802
15  Decatur M Train 8  Decatur M Train 8       T=0      Decatur M Train 8.T=0
16  Decatur M Train 8  Decatur M Train 8   T=5.802  Decatur M Train 8.T=5.802
17  Decatur M Train 9  Decatur M Train 9       T=0      Decatur M Train 9.T=0
18  Decatur M Train 9  Decatur M Train 9   T=5.802  Decatur M Train 9.T=5.802
19 Decatur F Train 10 Decatur F Train 10       T=0     Decatur F Train 10.T=0
20 Decatur F Train 10 Decatur F Train 10   T=5.802 Decatur F Train 10.T=5.802
21 Decatur F Train 11 Decatur F Train 11       T=0     Decatur F Train 11.T=0
22 Decatur F Train 11 Decatur F Train 11   T=5.802 Decatur F Train 11.T=5.802
23 Decatur F Train 12 Decatur F Train 12       T=0     Decatur F Train 12.T=0
24 Decatur F Train 12 Decatur F Train 12   T=5.802 Decatur F Train 12.T=5.802
25 Decatur F Train 13 Decatur F Train 13       T=0     Decatur F Train 13.T=0
26 Decatur F Train 13 Decatur F Train 13   T=5.802 Decatur F Train 13.T=5.802
27 Decatur F Train 14 Decatur F Train 14       T=0     Decatur F Train 14.T=0
28 Decatur F Train 14 Decatur F Train 14   T=5.802 Decatur F Train 14.T=5.802
29 Decatur F Train 15 Decatur F Train 15       T=0     Decatur F Train 15.T=0
30 Decatur F Train 15 Decatur F Train 15   T=5.802 Decatur F Train 15.T=5.802
31 Decatur F Train 16 Decatur F Train 16       T=0     Decatur F Train 16.T=0
32 Decatur F Train 16 Decatur F Train 16   T=5.802 Decatur F Train 16.T=5.802
33 Decatur F Train 17 Decatur F Train 17       T=0     Decatur F Train 17.T=0
34 Decatur F Train 17 Decatur F Train 17   T=5.802 Decatur F Train 17.T=5.802
35 Decatur F Train 18 Decatur F Train 18       T=0     Decatur F Train 18.T=0
36 Decatur F Train 18 Decatur F Train 18   T=5.802 Decatur F Train 18.T=5.802
37  Decatur M Test 19  Decatur M Test 19       T=0      Decatur M Test 19.T=0
38  Decatur M Test 19  Decatur M Test 19   T=5.802  Decatur M Test 19.T=5.802
39  Decatur M Test 20  Decatur M Test 20       T=0      Decatur M Test 20.T=0
40  Decatur M Test 20  Decatur M Test 20   T=5.802  Decatur M Test 20.T=5.802
41  Decatur M Test 21  Decatur M Test 21       T=0      Decatur M Test 21.T=0
42  Decatur M Test 21  Decatur M Test 21   T=5.802  Decatur M Test 21.T=5.802
43  Decatur M Test 22  Decatur M Test 22       T=0      Decatur M Test 22.T=0
44  Decatur M Test 22  Decatur M Test 22   T=5.802  Decatur M Test 22.T=5.802
45  Decatur M Test 23  Decatur M Test 23       T=0      Decatur M Test 23.T=0
46  Decatur M Test 23  Decatur M Test 23   T=5.802  Decatur M Test 23.T=5.802
47  Decatur M Test 24  Decatur M Test 24       T=0      Decatur M Test 24.T=0
48  Decatur M Test 24  Decatur M Test 24   T=5.802  Decatur M Test 24.T=5.802
49  Decatur M Test 25  Decatur M Test 25       T=0      Decatur M Test 25.T=0
50  Decatur M Test 25  Decatur M Test 25   T=5.802  Decatur M Test 25.T=5.802
51  Decatur M Test 26  Decatur M Test 26       T=0      Decatur M Test 26.T=0
52  Decatur M Test 26  Decatur M Test 26   T=5.802  Decatur M Test 26.T=5.802
53  Decatur M Test 27  Decatur M Test 27       T=0      Decatur M Test 27.T=0
54  Decatur M Test 27  Decatur M Test 27   T=5.802  Decatur M Test 27.T=5.802
55  Decatur F Test 28  Decatur F Test 28       T=0      Decatur F Test 28.T=0
56  Decatur F Test 28  Decatur F Test 28   T=5.802  Decatur F Test 28.T=5.802
57  Decatur F Test 29  Decatur F Test 29       T=0      Decatur F Test 29.T=0
58  Decatur F Test 29  Decatur F Test 29   T=5.802  Decatur F Test 29.T=5.802
59  Decatur F Test 30  Decatur F Test 30       T=0      Decatur F Test 30.T=0
60  Decatur F Test 30  Decatur F Test 30   T=5.802  Decatur F Test 30.T=5.802
61  Decatur F Test 31  Decatur F Test 31       T=0      Decatur F Test 31.T=0
62  Decatur F Test 31  Decatur F Test 31   T=5.802  Decatur F Test 31.T=5.802
63  Decatur F Test 32  Decatur F Test 32       T=0      Decatur F Test 32.T=0
64  Decatur F Test 32  Decatur F Test 32   T=5.802  Decatur F Test 32.T=5.802
65  Decatur F Test 33  Decatur F Test 33       T=0      Decatur F Test 33.T=0
66  Decatur F Test 33  Decatur F Test 33   T=5.802  Decatur F Test 33.T=5.802
67  Decatur F Test 34  Decatur F Test 34       T=0      Decatur F Test 34.T=0
68  Decatur F Test 34  Decatur F Test 34   T=5.802  Decatur F Test 34.T=5.802
69  Decatur F Test 35  Decatur F Test 35       T=0      Decatur F Test 35.T=0
70  Decatur F Test 35  Decatur F Test 35   T=5.802  Decatur F Test 35.T=5.802
71  Decatur F Test 36  Decatur F Test 36       T=0      Decatur F Test 36.T=0
72  Decatur F Test 36  Decatur F Test 36   T=5.802  Decatur F Test 36.T=5.802
73  Decatur F Test 37  Decatur F Test 37       T=0      Decatur F Test 37.T=0
74  Decatur F Test 37  Decatur F Test 37   T=5.802  Decatur F Test 37.T=5.802
75 Paulsboro-Train 38 Paulsboro-Train 38     T=2.2   Paulsboro-Train 38.T=2.2
76   Horsham-Train 39   Horsham-Train 39       T=2       Horsham-Train 39.T=2
77 Warminster-Test 40 Warminster-Test 40       T=2     Warminster-Test 40.T=2
#Multicheck plot

# Split Steady State Group into different populations for boxplot grouping
#df_check[df_check$Time.desc == "SteadyState" & grepl("Lubeck",df_check$Dataset),]$Time.desc <- "Lubeck"
#df_check[df_check$Time.desc == "SteadyState" & grepl("Little Hocking",df_check$Dataset),]$Time.desc <- "Little Hocking"

Modify aesthetics lookup table for boxplots

##  additional source aesthetic lookup table for grey-scale time (years);  merged legends save space on plotting output
times <- df_check%>% select(Time.desc, Time) %>%  unique () %>% 
  mutate(rank = rank(Time) , grey = grey.colors(start=1,end=0.4, n = n()),
         alpha = (rank)/8) %>% 
  select(-Time)
 
df_check <- df_check %>% mutate (legend_label = (paste0(City, "\n", Time.desc ) )) # add legend-labels
aes_lut <- df_check %>% 
  select(City, Train_Test, datatype,Time, Time.desc, legend_label) %>% unique () %>%
   left_join(aes_lut[, c("City", "cols")], by = "City") %>% ungroup () %>% unique ()%>%
   left_join (times, by = "Time.desc") %>% 
   arrange(datatype, City, Train_Test, Time)    %>% 
   mutate(alpha = if_else(City == "Horsham", alpha/2, alpha)) %>% # otherwise too dark with this color
  mutate_if(is.factor, as.character) 

Decatur boxplots

Changed grey start to 1 instead of 0.8, end at 0.6 instead of 0.4. Changed shape of symbols so they are filled.

##EF

df_decat  <- df_check %>%   
  filter(City == "Decatur" & Train_Test %in% c ("Train", "Test")) %>% 
  mutate(panel = ordered (Train_Test, levels = c ("Train", "Test"), 
                          labels = c("E: PFNA Decatur Train", "F: PFNA Decatur Test") ))

aes_lut_df_df_decat <- aes_lut %>% 
  filter(City == "Decatur" & Train_Test %in% c ("Train", "Test")) %>% 
  mutate_if(is.factor, as.character) 

source( paste0(gsub(basename(here()), 'shared_functions', here()), '/plot_sum_boxplot.r'))


plt_train <- plot_sum_boxplot   (dframe = df_decat, aes_lut= aes_lut_df_df_decat, facets = TRUE , pfas_nom = pfas_name     ) 
print(plt_train)

ggsave(here ("output-plots",paste0( sa,"DecaturTrainTestboxplot",pfas_name,".pdf")),plt_train,dpi=600)
Saving 6.5 x 3.5 in image

All boxplots

Changed grey start to 1 instead of 0.8, end at 0.6 instead of 0.4. Added shapes and fills to data points.

lets <- LETTERS;
names(lets)[1:(length(unique(df_check$dataset))-4)]<-as.character(unique(df_check$dataset))[5:length(unique(df_check$dataset))]

for (d in unique(df_check$dataset)) { # d = unique(df_check$dataset)[11]
    ddset <- df_check %>%    
    filter(dataset == d) 
    
    aes_lut_ddset <- ddset %>% select(legend_label,  City,Train_Test,datatype, Time.desc  ) %>% unique () %>% inner_join(aes_lut)
      
    gt <- ifelse(is.na(lets[d]),d,paste0(lets[d],": ", d))
    plt <- plot_sum_boxplot(dframe = ddset, aes_lut= aes_lut_ddset, gtitle= gt, facets = FALSE, pfas_nom = pfas_name)
     
  print(plt)
  ggsave(here ("output-plots",
                paste0( sa, d,"-boxplot-", 
                pfas_name,".pdf")) ,
         plt,dpi=600)

}
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector
Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector
Saving 6.5 x 3.5 in image
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector

Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector

Saving 6.5 x 3.5 in image
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector

Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector

Saving 6.5 x 3.5 in image
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector

Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector

Saving 6.5 x 3.5 in image
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector

Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector

Saving 6.5 x 3.5 in image
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector

Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector

Saving 6.5 x 3.5 in image
Joining, by = c("legend_label", "City", "Train_Test", "datatype", "Time.desc")
Warning: Column `City` joining factor and character vector, coercing into
character vector

Warning: Column `Train_Test` joining factor and character vector, coercing into
character vector

Saving 6.5 x 3.5 in image

### make Training plot  

df_d_trt <- df_check %>%   
     filter( (Train_Test == "Train") & ((Output_Var == "M_Cbgd_Css") | (Output_Var == "M_Cserum"))) %>%
     mutate_if(is.factor, as.character) %>%  # drop factor levels unused
     mutate(Dataset.Time = factor(Dataset.Time)) 
 

 aes_lut_df_d_trt <-  df_d_trt %>% select(City, datatype,Time, Time.desc, legend_label) %>% 
   inner_join(aes_lut  ) %>% 
   select(-Train_Test) %>% ungroup () %>% unique ()  
Joining, by = c("City", "datatype", "Time", "Time.desc", "legend_label")
plt_train <-    plot_sum_boxplot(dframe = df_d_trt, aes_lut= aes_lut_df_d_trt,   
                                 gtitle="A: Summary Data - Train" , facets = FALSE, pfas_nom = pfas_name )
  print(plt_train)

  ggsave(here ("output-plots", paste0( sa, "SummaryTrainDataboxplot",pfas_name,".pdf")), plt_train,dpi=600)
Saving 6.5 x 3.5 in image
###  make Test plot
df_d_test <- df_check %>%   
    filter((Train_Test == "Test") & 
             ((Output_Var == "M_Cbgd_Css") | (Output_Var == "M_Cserum")))  %>%
     mutate_if(is.factor, as.character) %>%  # drop factor levels unused
     mutate(Dataset.Time = factor(Dataset.Time)) 

aes_lut_df_d_test <-  df_d_test %>% select(City, datatype,Time, Time.desc, legend_label) %>% 
   inner_join(aes_lut  ) %>% 
   select(-Train_Test) %>% ungroup () %>% unique ()  
Joining, by = c("City", "datatype", "Time", "Time.desc", "legend_label")
plt_test <- plot_sum_boxplot(dframe = df_d_test, aes_lut= aes_lut_df_d_test, 
                             gtitle="B: Summary Data - Test", facets = FALSE, pfas_nom = pfas_name)
  print(plt_test)

  ggsave(here ("output-plots",paste0( sa, "SummaryTestDataboxplot",pfas_name,".pdf")), plt_test,dpi=600)  
Saving 6.5 x 3.5 in image

PFNA

Background posteriors

Shows shift in background estimate.

gmscale<-0.8

dat <- multicheck$parms.samp[,grep("M_ln_Cbgd",names(multicheck$parms.samp))]
datasetnames <- as.character(unique(calibdata$dataset))
datasetnames <- gsub(" Train","-Train",datasetnames)
datasetnames <- gsub(" Test","-Train",datasetnames)
datasetnames <- gsub(" M","",datasetnames)
datasetnames <- gsub(" F","",datasetnames)
datasetnames<-datasetnames[!duplicated(datasetnames)]
names(dat) <- datasetnames
dat <- dat[,grep("Train",names(dat))]
dat.df <- pivot_longer(dat,1:ncol(dat))
dat.df <- rbind(dat.df,
                data.frame(name="Prior",value=rnorm(5000,m=log(gmscale),sd=0.4055)))
dat.df$name <- factor(dat.df$name,levels=rev(
                        c("Prior",datasetnames[grep("Train",datasetnames)])))
dat.df$value <- exp(dat.df$value)

p<-ggplot(dat.df)+
  #geom_violin(aes(x=name,y=value,fill=name=="Prior"))+
  geom_boxplot(aes(x=name,y=value,fill=name=="Prior"),outlier.shape=NA)+
  scale_y_log10()+coord_flip()+
      scale_fill_manual(name=NULL, 
                    values=c("#009988", "#EE7733" ))+
  theme_classic() +  
  geom_hline(yintercept = gmscale,color="grey")+
  theme(legend.position="none",
      panel.background = element_rect(color="black",size=1))+
  ylab("Posterior shift in Background Concentration")

print(p)

ggsave(here ("output-plots",paste0( sa, "PFNA_GM_Cbgd.pdf")) ,p,dpi=600)
Saving 5 x 6 in image

Half-life

For PFNA, the population GM of the half-life has a posterior distribution that is narrower than the prior, with a posterior median (95% CI) estimate of 3.06 (2.16-4.37) years. The population GSD posterior is larger than the prior at 1.47(1.44-1.75).

dat <- multicheck$parms.samp[,c("M_ln_k.1.","V_ln_k.1.", "M_ln_Vd.1.", "SD_ln_Vd.1.")]
names(dat) <- c("M_ln_k(1)","V_ln_k(1)", "M_ln_Vd(1)", "SD_ln_Vd(1)")
  
set.seed(3.14159)
dat$z_ln_k <- rnorm(nrow(dat))
dat$z_ln_Vd <- rnorm(nrow(dat))
dat %>% rename_()
dat$ln_k_i <- dat$`M_ln_k(1)` + sqrt(dat$`V_ln_k(1)`)*dat$z_ln_k
dat$ln_Vd_i <- dat$`M_ln_Vd(1)`+ dat$`SD_ln_Vd(1)`*dat$z_ln_Vd
linmod <- lm(ln_Vd_i ~ ln_k_i,data=dat)
ggplot(dat) + geom_point(aes(ln_k_i,ln_Vd_i)) + 
  labs(subtitle=paste("Adj R2 =",signif(summary(linmod)$adj.r.squared,2)))

Check normality

qqnorm(dat$ln_k_i,main="ln k Q-Q Normal")
qqline(dat$ln_k_i,col="red")

plot(ecdf(dat$ln_k_i))
x <- seq(-3,1,0.01)
m_ln_k_i <-   mean(dat$ln_k_i)
sd_ln_k_i <- sd(dat$ln_k_i)
lines(x,pnorm(x,mean=m_ln_k_i,sd=sd_ln_k_i),col="red")
text(m_ln_k_i-2*sd_ln_k_i,0.9,paste("m =",signif(m_ln_k_i,4),"\nsd =",signif(sd_ln_k_i,4)))

qqnorm(dat$ln_Vd_i,main="ln Vd Q-Q Normal")
qqline(dat$ln_Vd_i,col="red")

plot(ecdf(dat$ln_Vd_i))
x <- seq(-3,1,0.01)
m_ln_Vd_i <- mean(dat$ln_Vd_i)
sd_ln_Vd_i <- sd(dat$ln_Vd_i)

lines(x,pnorm(x,mean=m_ln_Vd_i,sd=sd_ln_Vd_i),col="red")
text(m_ln_Vd_i-2*sd_ln_Vd_i,0.9,paste("m =",signif(m_ln_Vd_i,4),"\nsd =",signif(sd_ln_Vd_i,4)))

Calculate table values for individual-level

hl_i <- log(2)/ exp(dat$ln_k_i) # individual half-life 
med_hl_i <- paste(signif (median (hl_i), 3)) # median of individual half-life
ci_med_hl_i <-   paste(signif (quantile(hl_i, prob=c(0.025,0.975)), 3),collapse="-") # 95ci med individual halflife
ci98_med_hl_i <-   paste(signif (quantile(hl_i, prob=c(0.01,0.99)), 3),collapse="-") # 98ci med individual halflife
gm_hl_i <- paste(signif (exp(mean(log(hl_i))), 3)) # gm (which should be really close)
gsd_hl_i <- paste(signif (exp(sd(log(hl_i))), 3)) # gsd individual

med_Vd_i <- paste(signif (median(exp(dat$ln_Vd_i)), 3)) # median individual Vd
ci_med_Vd_i <-paste(signif (quantile(exp(dat$ln_Vd_i), prob=c(0.025,0.975)), 3),collapse="-") # 95ci med individual Vd
ci98_med_Vd_i <-paste(signif (quantile(exp(dat$ln_Vd_i), prob=c(0.01,0.99)), 3),collapse="-") # 98ci med individual Vd
gm_vd_i <- paste(signif (exp(mean(dat$ln_Vd_i)), 3)) # gm (which should be really close)
gsd_vd_i<- paste(signif (exp(sd(dat$ln_Vd_i)), 3)) # gsd indiv
PFNA_priors <- data.frame(
  halflife_GM= log(2)/rlnorm(50000,
                             meanlog=-1.80181,sdlog=0.4055))
M_k <- exp(as.numeric(dat$`M_ln_k(1)`))
PFNA_halflife_GM <- log(2)/M_k

PFNA_hlgm_pr_med <- signif(median(PFNA_priors$halflife_GM,3))
PFNA_hlgm_pr_med_95ci <-paste(signif(quantile(PFNA_priors$halflife_GM,
                                            prob=c(0.025,0.975)),
                                   3),
                            collapse="-")

PFNA_hl_median_gm <- signif(median(PFNA_halflife_GM),3)
PFNA_hl_median_gm_95ci <- paste(signif(quantile(PFNA_halflife_GM,
                                            prob=c(0.025,0.975)),3),collapse="-")

p<-ggplot()+
  stat_density(aes(halflife_GM, color = "Prior"),data=PFNA_priors,geom="line",size=2)+
  stat_density(aes(PFNA_halflife_GM,stat(density),color="Posterior"),geom="line",size=1.5)+
  xlim(0,15)+
  labs(title = bquote("E: PFNA"~T[1/2]~"Population GM")  ,
       subtitle=paste("Posterior Median (95% CI): ",
                      PFNA_hl_median_gm," (",
                      PFNA_hl_median_gm_95ci,
                      ")",sep=""))+
 xlab(bquote("Population GM"~T[1/2]~"(yrs)")) +
  scale_color_manual(name=NULL, 
                     values=c(Prior="#009988", Posterior="#EE7733" )) + 
  theme_classic() +  
  theme(legend.title = element_blank(),legend.position=c(0.8,0.7),
      panel.background = element_rect(color="black",size=1),
      legend.background = element_rect(fill="transparent", color=NA))
print(p)
Warning: Removed 41 rows containing non-finite values (stat_density).

ggsave(here ("output-plots", paste0( sa, "PFNA_hl_gm.pdf")) ,p,dpi=600)
Saving 4 x 2.5 in image
Warning: Removed 41 rows containing non-finite values (stat_density).
PFNA_priors$halflife_GSD =  exp(sqrt(exp(rnorm(50000,m=log(0.2000),sd=log(1.275))))) 
PFNA_halflife_GSD <- exp(sqrt(dat$`V_ln_k(1)`))

PFNA_hlgsd_pr_med <- signif(median(PFNA_priors$halflife_GSD,3))
PFNA_hlgsd_pr_med_95ci <-paste(signif(quantile(PFNA_priors$halflife_GSD,
                                            prob=c(0.025,0.975)),
                                   3),
                            collapse="-")
PFNA_hl_gsd_med <- signif(median(PFNA_halflife_GSD),3)
PFNA_hl_gsd_med_95ci <- paste(signif(quantile(PFNA_halflife_GSD,
                                            prob=c(0.025,0.975)),3),collapse="-")
p<-ggplot()+
  stat_density(aes(halflife_GSD, color = "Prior"),data=PFNA_priors,geom="line",size=2)+
  stat_density(aes(PFNA_halflife_GSD,stat(density), color = "Posterior"),geom="line",size=1.5)+
  xlim(1,3)+
  labs(title = bquote("F: PFNA"~T[1/2]~"Population GSD"), 
       subtitle=paste("Posterior Median (95% CI): ",
                      PFNA_hl_gsd_med," (",
                      PFNA_hl_gsd_med_95ci,
                      ")",sep=""))+
  xlab(bquote("Population GSD"~T[1/2]))+
  scale_color_manual(name=NULL, 
                     values=c(Prior="#009988", Posterior="#EE7733" )) + 
   theme_classic() +  
  theme(legend.title = element_blank(),legend.position=c(0.8,0.7),
      panel.background = element_rect(color="black",size=1),
      legend.background = element_rect(fill="transparent", color=NA))
print(p)

ggsave(here ("output-plots", paste0( sa, "PFNA_hl_gsd.pdf")), p,dpi=600)

Distribution Volume

For PFNA, the data were not particularly informative, but slightly increased the estimate of the median to 0.308(0.223-0.548) slightly. They were not informative as to the population GSD, with the posterior distributions essentially unchanged from the priors.

PFNA_priors$Vd_GM <- rlnorm(50000,
                             meanlog=-1.77196,
                             sdlog=0.2624)
PFNA_Vd_GM <- exp(dat$`M_ln_Vd(1)`)

 

PFNA_vd_gm_pr_med <- signif(median(PFNA_priors$Vd_GM,3))
PFNA_vd_gm_pr_med_95ci <- paste(signif(quantile(PFNA_priors$Vd_GM,
                                            prob=c(0.025,0.975)), 3), collapse="-")
PFNA_vd_gm_med <- signif(median(PFNA_Vd_GM),3)
PFNA_vd_gm_med_95ci <- paste(signif(quantile(PFNA_Vd_GM,
                                            prob=c(0.025,0.975)),3),collapse="-")

p<-ggplot()+
  stat_density(aes(Vd_GM, color = "Prior"),data=PFNA_priors,geom="line",size=2)+
  stat_density(aes(PFNA_Vd_GM,stat(density), color = "Posterior"),geom="line",size=1.5)+
  xlim(0,1)+labs(title = bquote("E: PFNA"~V[d]~"Population GM"),
                 subtitle=paste("Posterior Median (95% CI): ",
                                PFNA_vd_gm_med," (", 
                                PFNA_vd_gm_med_95ci,")",sep=""))+
   xlab(bquote("Population GM"~V[d]~"(l/kg)"))+
  scale_color_manual(name=NULL, 
                     values=c(Prior="#009988", Posterior="#EE7733" ))   +  
  theme_classic() +  
  theme(legend.title = element_blank(),legend.position=c(0.8,0.7),
      panel.background = element_rect(color="black",size=1),
      legend.background = element_rect(fill="transparent", color=NA))
print(p)

ggsave(here ("output-plots",paste0( sa, "PFNA_vd_gm.pdf")), p,dpi=600)
PFNA_priors$Vd_GSD = exp(abs(rnorm(50000,sd=0.17)))
PFNA_Vd_GSD <- exp(dat$`SD_ln_Vd(1)`)

PFNA_vd_gsd_pr_med <- signif(median(PFNA_priors$Vd_GSD,3))
PFNA_vd_gsd_pr_med_95ci <- paste(signif(quantile(PFNA_priors$Vd_GSD,
                                            prob=c(0.025,0.975)), 3), collapse="-")

PFNA_vd_gsd_med <- signif(median(PFNA_Vd_GSD),3)
PFNA_vd_gsd_med_95ci <- paste(signif(quantile(PFNA_Vd_GSD,
                                            prob=c(0.025,0.975)),3),collapse="-")

p<-ggplot()+
  stat_density(aes(Vd_GSD, color = "Prior"),data=PFNA_priors,geom="line",size=2)+
  stat_density(aes(PFNA_Vd_GSD,stat(density), color = "Posterior"),geom="line",size=1.5)+
  xlim(1,3)+
  labs(title = bquote("F: PFNA"~V[d]~"Population GSD "),
       subtitle=paste("Posterior Median (95% CI): ",
                      PFNA_vd_gsd_med," (",
                      PFNA_vd_gsd_med_95ci,
                      ")",sep=""))+
  xlab(bquote("Population GSD"~V[d]))+
  scale_color_manual(name=NULL, 
                     values=c(Prior="#009988", Posterior="#EE7733" )) +  
  theme_classic() +  
  theme(legend.title = element_blank(),legend.position=c(0.8,0.7),
      panel.background = element_rect(color="black",size=1),
      legend.background = element_rect(fill="transparent", color=NA))
print(p)

ggsave(here ("output-plots",paste0( sa, "PFNA_vd_gsd.pdf")), p,dpi=600)

Clearance (just pop GM)

Cl is k * Vd

PFNA_priors$CL_GM <- PFNA_priors$Vd_GM * (log(2)/PFNA_priors$halflife_GM)
PFNA_CL_GM <- exp(dat$`M_ln_Vd(1)` + dat$`M_ln_k(1)`)

PFNA_cl_gm_pr_med <- signif(median(PFNA_priors$CL_GM,3))
PFNA_cl_gm_pr_med_95ci <- paste(signif(quantile(PFNA_priors$CL_GM,
                                            prob=c(0.025,0.975)), 3), collapse="-")
PFNA_cl_gm_med <- signif(median(PFNA_CL_GM),3)
PFNA_cl_gm_med_95ci <- paste(signif(quantile(PFNA_CL_GM,
                                            prob=c(0.025,0.975)),3),collapse="-")

p<-ggplot()+
  stat_density(aes(CL_GM, color = "Prior"),data=PFNA_priors,geom="line",size=2)+
  stat_density(aes(PFNA_CL_GM,stat(density), color = "Posterior"),geom="line",size=1.5)+
  xlim(0,0.25)+labs(title = "C: PFNA Clearance Pop. GM ",subtitle=paste("Posterior Median (95% CI): ",
                                                                    PFNA_cl_gm_med," (",
                                                                    PFNA_cl_gm_med_95ci,
                                                                    ")",sep=""))+
  xlab("Pop. GM CL (l/(kg-yr))")+
  scale_color_manual(name=NULL, 
                     values=c(Prior="#009988", Posterior="#EE7733" )) +  
  theme_classic() +  
  theme(legend.title = element_blank(),legend.position=c(0.8,0.7),
      panel.background = element_rect(color="black",size=1),
      legend.background = element_rect(fill="transparent", color=NA))
print(p)

ggsave(here ("output-plots",paste0( sa, "PFNA_CL_gm.pdf")) ,p,dpi=600)

Table significant digit values

PFNA_hlgm_pr_med <- paste(signif(PFNA_hlgm_pr_med, 3))
PFNA_hl_median_gm<- paste(signif(PFNA_hl_median_gm, 3))
PFNA_hlgsd_pr_med<- paste(signif(PFNA_hlgsd_pr_med, 3))
PFNA_hl_gsd_med<- paste(signif(PFNA_hl_gsd_med, 3))
PFNA_vd_gm_pr_med<- paste(signif(PFNA_vd_gm_pr_med, 3))
PFNA_vd_gm_med<- paste(signif(PFNA_vd_gm_med, 3))
PFNA_vd_gsd_pr_med<- paste(signif(PFNA_vd_gsd_pr_med, 3))
PFNA_vd_gsd_med<- paste(signif(PFNA_vd_gsd_med, 3))
PFNA_cl_gm_pr_med<- paste(signif(PFNA_cl_gm_pr_med, 3))
PFNA_cl_gm_med<- paste(signif(PFNA_cl_gm_med, 3))

Population median estimates [95% CI]

Parameter Prior GM Posterior GM Prior GSD Posterior GSD
Half-life (years) 4.2 2.35 1.56 1.53
HL [95% CI] [1.89-9.37] [1.65-3.16] [1.42-1.77] [1.4-1.7]
Volume of distribution 0.17 0.186 1.12 1.12
\(V_D\) [95% CI] [0.102-0.284] [0.113-0.302] [1.01-1.46] [1.01-1.51]
Clearance 0.028 0.0559
\(CL\) [95% CI] [0.0108-0.0727] [0.0327-0.0932] [] []

Individual Posterior estimates

Parameter median GM [95% CI] [[98% CI]] GM calculator input GSD individual
Half-life (years) 2.27 [ 0.826-5.36 ] [[ 0.758-5.94 ]] 2.27 1.61
Volume of distribution \(V_D\) 0.183 [ 0.0998-0.324 ] [[ 0.085-0.398 ]] 0.185 1.35
─ Session info ───────────────────────────────────────────────────────────────
 setting  value                       
 version  R version 3.6.1 (2019-07-05)
 os       Oracle Linux Server 7.9     
 system   x86_64, linux-gnu           
 ui       X11                         
 language (EN)                        
 collate  en_US.UTF-8                 
 ctype    en_US.UTF-8                 
 tz       America/New_York            
 date     2021-03-28                  

─ Packages ───────────────────────────────────────────────────────────────────
 package     * version date       lib source        
 assertthat    0.2.1   2019-03-21 [2] CRAN (R 3.6.1)
 backports     1.1.5   2019-10-02 [2] CRAN (R 3.6.1)
 base64enc     0.1-3   2015-07-28 [2] CRAN (R 3.6.1)
 bayesplot   * 1.7.0   2019-05-23 [2] CRAN (R 3.6.1)
 broom         0.5.2   2019-04-07 [2] CRAN (R 3.6.1)
 callr         3.3.2   2019-09-22 [2] CRAN (R 3.6.1)
 cellranger    1.1.0   2016-07-27 [2] CRAN (R 3.6.1)
 cli           1.1.0   2019-03-19 [2] CRAN (R 3.6.1)
 coda        * 0.19-3  2019-07-05 [2] CRAN (R 3.6.1)
 codetools     0.2-16  2018-12-24 [2] CRAN (R 3.6.1)
 colorspace    1.4-1   2019-03-18 [2] CRAN (R 3.6.1)
 crayon        1.3.4   2017-09-16 [2] CRAN (R 3.6.1)
 DBI           1.0.0   2018-05-02 [2] CRAN (R 3.6.1)
 dbplyr        1.4.2   2019-06-17 [2] CRAN (R 3.6.1)
 desc          1.2.0   2018-05-01 [2] CRAN (R 3.6.1)
 devtools      2.2.1   2019-09-24 [2] CRAN (R 3.6.1)
 digest        0.6.23  2019-11-23 [2] CRAN (R 3.6.1)
 dplyr       * 0.8.3   2019-07-04 [2] CRAN (R 3.6.1)
 ellipsis      0.3.0   2019-09-20 [2] CRAN (R 3.6.1)
 evaluate      0.14    2019-05-28 [2] CRAN (R 3.6.1)
 farver        2.0.1   2019-11-13 [2] CRAN (R 3.6.1)
 forcats     * 0.4.0   2019-02-17 [2] CRAN (R 3.6.1)
 fs            1.3.1   2019-05-06 [2] CRAN (R 3.6.1)
 generics      0.0.2   2018-11-29 [2] CRAN (R 3.6.1)
 ggplot2     * 3.2.1   2019-08-10 [2] CRAN (R 3.6.1)
 ggridges      0.5.1   2018-09-27 [2] CRAN (R 3.6.1)
 ggsci       * 2.9     2018-05-14 [2] CRAN (R 3.6.1)
 glue          1.3.1   2019-03-12 [2] CRAN (R 3.6.1)
 gtable        0.3.0   2019-03-25 [2] CRAN (R 3.6.1)
 haven         2.2.0   2019-11-08 [2] CRAN (R 3.6.1)
 here        * 0.1     2017-05-28 [2] CRAN (R 3.6.1)
 hms           0.5.2   2019-10-30 [2] CRAN (R 3.6.1)
 htmltools     0.4.0   2019-10-04 [2] CRAN (R 3.6.1)
 httr          1.4.1   2019-08-05 [2] CRAN (R 3.6.1)
 jsonlite      1.6     2018-12-07 [2] CRAN (R 3.6.1)
 khroma      * 1.4.0   2020-10-05 [1] CRAN (R 3.6.1)
 knitr         1.26    2019-11-12 [2] CRAN (R 3.6.1)
 labeling      0.3     2014-08-23 [2] CRAN (R 3.6.1)
 lattice       0.20-38 2018-11-04 [2] CRAN (R 3.6.1)
 lazyeval      0.2.2   2019-03-15 [2] CRAN (R 3.6.1)
 lifecycle     0.1.0   2019-08-01 [2] CRAN (R 3.6.1)
 lubridate     1.7.4   2018-04-11 [2] CRAN (R 3.6.1)
 magrittr      1.5     2014-11-22 [2] CRAN (R 3.6.1)
 memoise       1.1.0   2017-04-21 [2] CRAN (R 3.6.1)
 modelr        0.1.5   2019-08-08 [2] CRAN (R 3.6.1)
 munsell       0.5.0   2018-06-12 [2] CRAN (R 3.6.1)
 nlme          3.1-142 2019-11-07 [2] CRAN (R 3.6.1)
 pillar        1.4.2   2019-06-29 [2] CRAN (R 3.6.1)
 pkgbuild      1.0.6   2019-10-09 [2] CRAN (R 3.6.1)
 pkgconfig     2.0.3   2019-09-22 [2] CRAN (R 3.6.1)
 pkgload       1.0.2   2018-10-29 [2] CRAN (R 3.6.1)
 plyr          1.8.4   2016-06-08 [2] CRAN (R 3.6.1)
 prettyunits   1.0.2   2015-07-13 [2] CRAN (R 3.6.1)
 processx      3.4.1   2019-07-18 [2] CRAN (R 3.6.1)
 ps            1.3.0   2018-12-21 [2] CRAN (R 3.6.1)
 purrr       * 0.3.3   2019-10-18 [2] CRAN (R 3.6.1)
 R6            2.4.1   2019-11-12 [2] CRAN (R 3.6.1)
 Rcpp          1.0.3   2019-11-08 [2] CRAN (R 3.6.1)
 readr       * 1.3.1   2018-12-21 [2] CRAN (R 3.6.1)
 readxl        1.3.1   2019-03-13 [2] CRAN (R 3.6.1)
 remotes       2.1.0   2019-06-24 [2] CRAN (R 3.6.1)
 reprex        0.3.0   2019-05-16 [2] CRAN (R 3.6.1)
 reshape2    * 1.4.3   2017-12-11 [2] CRAN (R 3.6.1)
 rlang         0.4.2   2019-11-23 [2] CRAN (R 3.6.1)
 rmarkdown     1.18    2019-11-27 [2] CRAN (R 3.6.1)
 rprojroot     1.3-2   2018-01-03 [2] CRAN (R 3.6.1)
 rstudioapi    0.10    2019-03-19 [2] CRAN (R 3.6.1)
 rvest         0.3.5   2019-11-08 [2] CRAN (R 3.6.1)
 scales        1.1.0   2019-11-18 [2] CRAN (R 3.6.1)
 sessioninfo   1.1.1   2018-11-05 [2] CRAN (R 3.6.1)
 stringi       1.4.3   2019-03-12 [2] CRAN (R 3.6.1)
 stringr     * 1.4.0   2019-02-10 [2] CRAN (R 3.6.1)
 testthat      2.3.0   2019-11-05 [2] CRAN (R 3.6.1)
 tibble      * 2.1.3   2019-06-06 [2] CRAN (R 3.6.1)
 tidyr       * 1.0.0   2019-09-11 [2] CRAN (R 3.6.1)
 tidyselect    0.2.5   2018-10-11 [2] CRAN (R 3.6.1)
 tidyverse   * 1.3.0   2019-11-21 [2] CRAN (R 3.6.1)
 usethis       1.5.1   2019-07-04 [2] CRAN (R 3.6.1)
 vctrs         0.2.0   2019-07-05 [2] CRAN (R 3.6.1)
 withr         2.1.2   2018-03-15 [2] CRAN (R 3.6.1)
 xfun          0.11    2019-11-12 [2] CRAN (R 3.6.1)
 xml2          1.2.2   2019-08-09 [2] CRAN (R 3.6.1)
 yaml          2.2.0   2018-07-25 [2] CRAN (R 3.6.1)
 zeallot       0.1.0   2018-01-28 [2] CRAN (R 3.6.1)

[1] /home/ad.abt.local/wchiu/R/library
[2] /opt/R/3.6.1/lib64/R/library
LS0tCnRpdGxlOiAiUEZOQSAxIGNvbXBhcnRtZW50IFBsb3RzICh2OCkiCmF1dGhvcjogIldlaWhzdWVoIENoaXUsIENsYWlyZSBMYXksIFBhcmtlciBNYWxlayIKZGF0ZTogImByIGZvcm1hdChTeXMudGltZSgpLCAnJUYnKWAiCmtuaXQ6IChmdW5jdGlvbihpbnB1dEZpbGUsIGVuY29kaW5nKSB7b3V0ZGlyID0gZmlsZS5wYXRoKGRpcm5hbWUoaW5wdXRGaWxlKSwgJ21hcmtkb3duJywgcGFzdGUwKGZvcm1hdChTeXMudGltZSgpLCAnJUYnKSkpOyBpZighZGlyLmV4aXN0cyhvdXRkaXIpKXtkaXIuY3JlYXRlKG91dGRpcil9OyBybWFya2Rvd246OnJlbmRlcihpbnB1dEZpbGUsIGVuY29kaW5nID0gZW5jb2RpbmcsIG91dHB1dF9mb3JtYXQgPSAnYWxsJywgb3V0cHV0X2RpciA9IG91dGRpcikgfSkKb3V0cHV0OgogIHdvcmRfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBkZl9wcmludDoga2FibGUKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDUKLS0tCgpgYGB7ciBzZXR1cH0KbGlicmFyeShjb2RhKQpsaWJyYXJ5KGJheWVzcGxvdCkgCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3NjaSkKbGlicmFyeShraHJvbWEpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHJlc2hhcGUyKQpsaWJyYXJ5KGhlcmUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgZHBpID0gMzAwICkKYGBgCgpTZXQgdXAgTUNTaW0gZmlsZSAKCmBgYHtyIG1jc2ltfQojIHRoaXMgbWFya2Rvd24gZmlsZSBtdXN0IGJlIHNhdmVkIGluIHRvcCBsZXZlbCBkaXJlY3RvcnkgZm9yIHRoZSBmb2xsb3dpbmcgdG8gd29yazsgdGhlIG1jc2ltIGNvZGUgZGVwZW5kcyBvbiBnZXR3ZCByZXN1bHRzLgptZGlyIDwtICJNQ1NpbSIKc291cmNlKGhlcmU6OmhlcmUobWRpciwic2V0dXBfTUNTaW0uUiIpKQojIE1ha2UgbW9kLmV4ZSAodXNlZCB0byBjcmVhdGUgbWNzaW0gZXhlY3V0YWJsZSBmcm9tIG1vZGVsIGZpbGUpCm1ha2Vtb2QoKSAKYGBgCgojIyBTZXQgZmlsZW5hbWVzIGFuZCBsb2FkIGRhdGEKCgpgYGB7ciBNQ01DICBtb2RlbCBmaWxlLCBpbmNsdWRlPUZBTFNFfQpzZXQuc2VlZCgzMTQxNTkpCnNhIDwtICJDYmdkLTgwXyIgIyBBREQgc2Vuc2l0aXZpdHkgdGVzdCB0YWcgdG8gcGxvdCBmaWxlbmFtZXM6IE1fbG5fQ2JnZF9zYyB0byBiZSBjZW50ZXJlZCBvbiBsbigwLjgpIGluc3RlYWQgb2YgMCAoZGVjcmVhc2VkIGJ5IDIwJSkKCiMgTWFrZSBtb2RlbCBleGVjdXRhYmxlCm1vZGVsX2ZpbGU8LSAiUEZBU18xY3B0X3Y4LnBvcC5NQ01DLm1vZGVsLlIiCm1ha2VtY3NpbShtb2RlbF9maWxlKQoKaW5fZmlsZSA8LSAiUEZOQV8xY3B0X3Y4LlBvcE1DTUNfTWVhbkluZGl2VHJhaW5UZXN0LmluLlIiIApwZmFzX25hbWUgPC0gZ3N1YigiXzFjcHRfdjguUG9wTUNNQ19NZWFuSW5kaXZUcmFpblRlc3QuaW4uUiIsICIiLCBpbl9maWxlKQoKc2FtcHMgPC0gZGF0YS5mcmFtZSgpCmNoZWNrcyA8LSBkYXRhLmZyYW1lKCkKc2FtcHMubGlzdCA8LSBsaXN0KCkKZm9yIChjaGFpbm51bSBpbiAxOjQpIHsKICBvbmVjaGFpbiA8LSByZWFkLmRlbGltKHN1YigiLmluLlIiLHBhc3RlMChjaGFpbm51bSwiLm91dCIpLGluX2ZpbGUpKQogIHNhbXBzLmxpc3RbW2NoYWlubnVtXV08LW1jbWMob25lY2hhaW5bZmxvb3IobnJvdyhvbmVjaGFpbikgLyAyKTpucm93KG9uZWNoYWluKSwgLTFdKQogIHNhbXBzIDwtIHJiaW5kKHNhbXBzLHNhbXBzLmxpc3RbW2NoYWlubnVtXV0pCiAgb25lY2hlY2sgPC0gcmVhZC5kZWxpbShzdWIoIi5pbi5SIixwYXN0ZTAoY2hhaW5udW0sIi5jaGVjay5vdXQiKSxpbl9maWxlKSkKICBvbmVjaGVjayRDaGFpbiA8LSBjaGFpbm51bQogIGNoZWNrcyA8LSByYmluZChjaGVja3Msb25lY2hlY2spCn0Kc2FtcHMubWNtY2xpc3QgPC0gYXMubWNtYy5saXN0KHNhbXBzLmxpc3QpCgpsb2FkKCJQRk5BXzFjcHRfdjhfbXVsdGljaGVjay5SZGF0YSIpCmBgYAoKIyMgU2V0IHVwIGRhdGFzZXQKCmBgYHtyIGRhdGFzZXQtTFVULCBjYWNoZSA9IFRSVUV9CmlkX2x1dCA8LSBtdWx0aWNoZWNrJGRmX2NoZWNrICU+JSBzZWxlY3QoTGV2ZWwpICU+JSB1bmlxdWUgKCkgICU+JQogIG11dGF0ZShkYXRhc2V0ID0gYyggCiAgICByZXAoIkRlY2F0dXIgTSBUcmFpbiIsIDkpLAogICAgcmVwKCJEZWNhdHVyIEYgVHJhaW4iLCA5KSwKICAgIHJlcCgiRGVjYXR1ciBNIFRlc3QiLCA5KSwKICAgIHJlcCgiRGVjYXR1ciBGIFRlc3QiLCAxMCksCiAgICAnUGF1bHNib3JvLVRyYWluJywnSG9yc2hhbS1UcmFpbicsCiAgICAnV2FybWluc3Rlci1UZXN0JyksIAogICAgU2V4ID0gYyggCiAgICByZXAoIk0iLCA5KSwKICAgIHJlcCgiRiIsIDkpLAogICAgcmVwKCJNIiwgOSksCiAgICByZXAoIkYiLCAxMCksCiAgICAnTWl4ZWQnLCAnTWl4ZWQnLCAgJ01peGVkJyksCiAgICBDaXR5ID0gYyggCiAgICByZXAoIkRlY2F0dXIiLCAxOCksCiAgICByZXAoIkRlY2F0dXIiLCAxOSksCiAgICAnUGF1bHNib3JvJywnSG9yc2hhbScsJ1dhcm1pbnN0ZXInKSwgCiAgICBUcmFpbl9UZXN0ID0gYyggCiAgICByZXAoIlRyYWluIiwgOSksCiAgICByZXAoIlRyYWluIiwgOSksCiAgICByZXAoIlRlc3QiLCA5KSwKICAgIHJlcCgiVGVzdCIsIDEwKSwKICAgICdUcmFpbicsICAnVHJhaW4nLCAnVGVzdCcpLAogICAgZGF0YXR5cGUgPSBjKAogICAgICByZXAoIkluZGl2aWR1YWwiLDkrOSs5KzEwKSwKICAgICAgcmVwKCJTdW1tYXJ5IiwzKSksCiAgICBTaW11bGF0aW9uID0gcm93X251bWJlcigpLAogICAgdmFyaWFibGUgPSBwYXN0ZTAoZGF0YXNldCwgIiAiLFNpbXVsYXRpb24pKQoKaWRfbHV0JGRhdGFzZXQgPC0gZmFjdG9yKGlkX2x1dCRkYXRhc2V0LGxldmVscz0KICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiRGVjYXR1ciBNIFRyYWluIiwiRGVjYXR1ciBGIFRyYWluIiwiQXJuc2JlcmcgTSBUcmFpbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkFybnNiZXJnIEYgVHJhaW4iLCJEZWNhdHVyIE0gVGVzdCIsIkRlY2F0dXIgRiBUZXN0IiwiQXJuc2JlcmcgTSBUZXN0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQXJuc2JlcmcgRiBUZXN0IiwiTWlubmVzb3RhIFRyYWluIiwiTWlubmVzb3RhIFRlc3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICdMdWJlY2stQmFydGVsbC1UcmFpbicsICdMdWJlY2stQmFydGVsbC1UZXN0JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnTGl0dGxlIEhvY2tpbmctQmFydGVsbC1UcmFpbicsICdMaXR0bGUgSG9ja2luZy1CYXJ0ZWxsLVRlc3QnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICdMaXR0bGUgSG9ja2luZy1FbW1ldHQtVGVzdCcsJ1BhdWxzYm9yby1UcmFpbicsJ0hvcnNoYW0tVHJhaW4nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICdXYXJtaW5zdGVyLVRlc3QnLCdXYXJyaW5ndG9uLVRyYWluJykpCmlkX2x1dCRDaXR5IDwtIGZhY3RvcihpZF9sdXQkQ2l0eSxsZXZlbHMgPSAKICAgICAgICAgICAgICAgICAgICAgICAgYygiRGVjYXR1ciIsIkFybnNiZXJnIiwiTWlubmVzb3RhIiwnTHViZWNrLUJhcnRlbGwnLAogICAgICAgICAgICAgICAgICAgICAgICAgICdMaXR0bGUgSG9ja2luZy1CYXJ0ZWxsJywnTGl0dGxlIEhvY2tpbmctRW1tZXR0JywKICAgICAgICAgICAgICAgICAgICAgICAgICAnUGF1bHNib3JvJywnSG9yc2hhbScsJ1dhcm1pbnN0ZXInLCdXYXJyaW5ndG9uJykpCiAKaW5kaXZfbHV0IDwtIGlkX2x1dCAlPiUgCiAgZmlsdGVyKENpdHkgJWluJSBjKCJEZWNhdHVyIikpICU+JQogIG11dGF0ZSggIGRhdGFzZXQgPSBhcy5mYWN0b3IoZGF0YXNldCkpCgpudiA8LSBkYXRhLmZyYW1lKGRhdGFzZXQgPXVuaXF1ZShpbmRpdl9sdXQkZGF0YXNldCksIAogICAgICAgICAgIHZhcmlhYmxlPSByZXAoIlBvcCBHTSIsIDQpLAogICAgICAgICAgIHR5cGU9IHJlcCgiUG9wIEdNIiwgNCksIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKYGBgCgoKIyMgU2NhdHRlciBwbG90IG9mIHByZWRpY3Rpb25zIChtZWRpYW4gb2YgbXVsdGljaGVjayBzYW1wbGVzKSB2ZXJzdXMgZGF0YS4KClRoaXMgaXMgYSBGaWd1cmUgMiBwYW5lbC4gIE5lZWRlZCB0byB1c2UgInNjYWxlPTEuMSIgaW4gZ2dzYXZlIHRvIG1hdGNoIFBGT0EuCgpgYGB7ciBwcmVkaWN0aW9uLXZlcnN1cy1kYXRhICwgY2FjaGUgPSBUUlVFLGZpZy5oZWlnaHQ9My41LGZpZy53aWR0aD04LGRwaT02MDB9Cm5yb3cobXVsdGljaGVjayRkZl9jaGVjaykKbnJvdyhpZF9sdXQpCm11bHRpY2hlY2skZGZfY2hlY2sgJT4lIGxlZnRfam9pbihpZF9sdXQpICU+JSBucm93KCkKCm5hbWVzKG11bHRpY2hlY2skZGZfY2hlY2spCgptdWx0aWNoZWNrMiA8LSBtdWx0aWNoZWNrJGRmX2NoZWNrICU+JSBsZWZ0X2pvaW4oaWRfbHV0KSU+JSAKICBncm91cF9ieV9hdCAoIHZhcnMoLVByZWRpY3Rpb24pKSAlPiUgCiAgc3VtbWFyaXNlKFByZWRpY3Rpb24gPSBtZWRpYW4oUHJlZGljdGlvbikpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShDaXR5KSAlPiUgCiAgbXV0YXRlKFRyYWluX1Rlc3QgPSBmYWN0b3IoVHJhaW5fVGVzdCwgbGV2ZWxzID0gYygiVHJhaW4iLCAiVGVzdCIpKSwKICAgICAgICAgYENpdHkgKGRhdGF0eXBlKWAgPSBmYWN0b3IgKHBhc3RlMChDaXR5LCAiXG4oIiwgZGF0YXR5cGUsICIpXG4iKSApLAogICAgICAgICBsYWJlbCA9IGNhc2Vfd2hlbihUcmFpbl9UZXN0PT0iVHJhaW4iIH4gIkU6IFBGTkEgVHJhaW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICBUcmFpbl9UZXN0PT0iVGVzdCIgIH4gIkY6IFBGTkEgVGVzdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiIikpCiAKCiAjZGVmaW5lIGNvbG9yIGZvciB0ZXN0aW5nIGJveHBsb3RzCmJwX2NvbHMgPC0gYyAoYXMuY2hhcmFjdGVyIChraHJvbWE6OmNvbG91cigibXV0ZWQiKSg5KSkgLCAiIzE5MTkxOSIpICAgCmJwX2NvbHMgPC1icF9jb2xzW2MoMSwgNywgOTo4KV0jIHBsb3Rfc2NoZW1lX2NvbG91cmJsaW5kKGJwX2NvbHMpIAoKIyMjIENyZWF0ZSBhZXN0aGV0aWNzIGxvb2t1cAphZXNfbHV0IDwtIG11bHRpY2hlY2syICU+JSB1bmdyb3VwKCkgJT4lIAogIGdyb3VwX2J5KENpdHksIGRhdGF0eXBlLCAgYENpdHkgKGRhdGF0eXBlKWAgKSAlPiUgc3VtbWFyaXNlICgpICU+JSB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKCBjb2xzID0gYnBfY29scywgY2l0eV9maWxscyA9ICAgYnBfY29scyAsIAogICAgICAgICAgIyBmb3IgaW5kaXZpZHVhbCBsZXZlbCBvbiBwb2ludCBwbG90IChtdWx0aWNoZWNrMiksIGRhcmtlbiBvdXRsaW5lcyBmb3IgdmlzaWJpbGl0eSwgdXNlIHN0YW5kYXJkIGNvbG9ycyBvdGhlcndpc2UKICAgICAgICAgY2l0eV9vdXRsaW5lcyA9ICBpZl9lbHNlKGRhdGF0eXBlID09ICJJbmRpdmlkdWFsIiAgLCAgY29sb3JzcGFjZTo6ZGFya2VuKGNpdHlfZmlsbHMsIDAuMyksIGNpdHlfZmlsbHMpICwgIAogICAgICAgICBzaGFwZXMgPSBjYXNlX3doZW4oZGF0YXR5cGUgPT0gIkluZGl2aWR1YWwiICAmIGBDaXR5YCAlaW4lIGMoJ0RlY2F0dXInLCAnQXJuc2JlcmcnLCAnTWlubmVzb3RhJykgICB+ICAyMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGF0eXBlID09ICJTdW1tYXJ5IiAmYENpdHlgICVpbiUgYygiSG9yc2hhbSIsICJXYXJtaW5zdGVyIiwgICJXYXJyaW5ndG9uIikgfiAyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YXR5cGUgPT0gIlN1bW1hcnkiICYgYENpdHlgID09ICJQYXVsc2Jvcm8iIH4gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAxOCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwgCiAgICAgICAgIHNpemUgPSBpZl9lbHNlKGRhdGF0eXBlID09IkluZGl2aWR1YWwiLCAxLjc1LCAyLjUgKSApICAKCgoKc291cmNlKCBwYXN0ZTAoZ3N1YihiYXNlbmFtZShoZXJlKCkpLCAnc2hhcmVkX2Z1bmN0aW9ucycsIGhlcmUoKSksICcvcGxvdF9zY2F0dGVyX21jaGVjay5yJykpCgpwMiA8LSBwbG90X3NjYXR0ZXJfbWNoZWNrKGRmcmFtZSA9IG11bHRpY2hlY2syLCBwZmFzX25vbSA9IHBmYXNfbmFtZSwgYWVzX2x1dF9mbiA9IGFlc19sdXQgKQpwcmludChwMikgCmdnc2F2ZShoZXJlICgib3V0cHV0LXBsb3RzIiwgcGFzdGUwKCBzYSwibXVsdGljaGVja3Bsb3RfIiwgcGZhc19uYW1lLAogICAgICAgICAgICAgICAiLnBkZiIpKSxwMixkcGk9NjAwLCBzY2FsZT0xLjEpCgpgYGAKCiMjIFBhcnNlIG11bHRpY2hlY2sKCmBgYHtyIGRvLW11bHRpY2hlY2ssIGNhY2hlID0gVFJVRSwgZmlnLndpZHRoPTYsIGZpZy5oZWlnaHQ9MTh9CgpkZl9jaGVjayA8LSBtdWx0aWNoZWNrJGRmX2NoZWNrCmRmX2NoZWNrIDwtIHN1YnNldChkZl9jaGVjayxEYXRhID4gMCkgCgpuMSA8LSBucm93KGRmX2NoZWNrKQppZF9jaGtzIDwtIGRmX2NoZWNrICU+JSBzZWxlY3QoTGV2ZWwpICU+JSB1bmlxdWUoKSAlPiUgYmluZF9jb2xzKGlkX2x1dCkgICU+JQogIG11dGF0ZShkYXRhc2V0ID0gYXMuZmFjdG9yKGRhdGFzZXQpLCBTZXggPSBhcy5mYWN0b3IoU2V4KSwgQ2l0eSA9IGFzLmZhY3RvcihDaXR5KSwgCiAgICAgICAgIFRyYWluX1Rlc3QgPSBhcy5mYWN0b3IoVHJhaW5fVGVzdCkpCgpkZl9jaGVjayA8LSBkZl9jaGVjayAlPiUgbGVmdF9qb2luKGlkX2Noa3MsIGJ5ID0gIlNpbXVsYXRpb24iKSU+JQogIG11dGF0ZShEYXRhc2V0ID0gcGFzdGUoYXMuY2hhcmFjdGVyKGRhdGFzZXQpLCBTaW11bGF0aW9uKSwKICAgICAgICAgU2V4ID0gb3JkZXJlZChTZXgsIGxldmVscyA9IGMoIk0iLCAiRiIsICJNaXhlZCIpLCAKICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJNYWxlIiwgIkZlbWFsZSIsICJNaXhlZCAoYWxsIHNleGVzKSIpKSkKbjIgPC0gbnJvdyhkZl9jaGVjaykKaWYobjEgIT0gbjIpcHJpbnQoImR1cGxpY2F0ZXMgY3JlYXRlZCBpbiBpZC1sdXQgam9pbiIpCmBgYAoKCmBgYHtyIGRvLW11bHRpY2hlY2stMiwgY2FjaGUgPSBUUlVFLCBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD0xOH0KZGZfY2hlY2skVGltZS5kZXNjIDwtIGFzLmNoYXJhY3RlcihwYXN0ZTAoIlQ9IixkZl9jaGVjayRUaW1lKSkKZGZfY2hlY2skVGltZS5kZXNjW2RmX2NoZWNrJFRpbWUuZGVzYyA9PSAiVD0xZS0wNiJdIDwtICJTdGVhZHlTdGF0ZSIKZGZfY2hlY2skRGF0YXNldC5UaW1lIDwtIGludGVyYWN0aW9uKGRmX2NoZWNrJERhdGFzZXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZl9jaGVjayRUaW1lLmRlc2MsbGV4Lm9yZGVyPVRSVUUpCmRmX2NoZWNrJERhdGFzZXQuVGltZSA8LSBmYWN0b3IoZGZfY2hlY2skRGF0YXNldC5UaW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscz1sZXZlbHMoZGZfY2hlY2skRGF0YXNldC5UaW1lKSkKY2FsaWJkYXRhIDwtIGRmX2NoZWNrWyxuYW1lcyhkZl9jaGVjaykgIT0gIlByZWRpY3Rpb24iXQpjYWxpYmRhdGEgPC0gY2FsaWJkYXRhWyFkdXBsaWNhdGVkKGNhbGliZGF0YSksXQpwcmludChjYWxpYmRhdGEpCiAKI011bHRpY2hlY2sgcGxvdAoKIyBTcGxpdCBTdGVhZHkgU3RhdGUgR3JvdXAgaW50byBkaWZmZXJlbnQgcG9wdWxhdGlvbnMgZm9yIGJveHBsb3QgZ3JvdXBpbmcKI2RmX2NoZWNrW2RmX2NoZWNrJFRpbWUuZGVzYyA9PSAiU3RlYWR5U3RhdGUiICYgZ3JlcGwoIkx1YmVjayIsZGZfY2hlY2skRGF0YXNldCksXSRUaW1lLmRlc2MgPC0gIkx1YmVjayIKI2RmX2NoZWNrW2RmX2NoZWNrJFRpbWUuZGVzYyA9PSAiU3RlYWR5U3RhdGUiICYgZ3JlcGwoIkxpdHRsZSBIb2NraW5nIixkZl9jaGVjayREYXRhc2V0KSxdJFRpbWUuZGVzYyA8LSAiTGl0dGxlIEhvY2tpbmciCmBgYAoKTW9kaWZ5IGFlc3RoZXRpY3MgbG9va3VwIHRhYmxlIGZvciBib3hwbG90cyAKYGBge3IgbW9kLWFlcy1sdXR9CiMjICBhZGRpdGlvbmFsIHNvdXJjZSBhZXN0aGV0aWMgbG9va3VwIHRhYmxlIGZvciBncmV5LXNjYWxlIHRpbWUgKHllYXJzKTsgIG1lcmdlZCBsZWdlbmRzIHNhdmUgc3BhY2Ugb24gcGxvdHRpbmcgb3V0cHV0CnRpbWVzIDwtIGRmX2NoZWNrJT4lIHNlbGVjdChUaW1lLmRlc2MsIFRpbWUpICU+JSAgdW5pcXVlICgpICU+JSAKICBtdXRhdGUocmFuayA9IHJhbmsoVGltZSkgLCBncmV5ID0gZ3JleS5jb2xvcnMoc3RhcnQ9MSxlbmQ9MC40LCBuID0gbigpKSwKICAgICAgICAgYWxwaGEgPSAocmFuaykvOCkgJT4lIAogIHNlbGVjdCgtVGltZSkKIApkZl9jaGVjayA8LSBkZl9jaGVjayAlPiUgbXV0YXRlIChsZWdlbmRfbGFiZWwgPSAocGFzdGUwKENpdHksICJcbiIsIFRpbWUuZGVzYyApICkpICMgYWRkIGxlZ2VuZC1sYWJlbHMKYWVzX2x1dCA8LSBkZl9jaGVjayAlPiUgCiAgc2VsZWN0KENpdHksIFRyYWluX1Rlc3QsIGRhdGF0eXBlLFRpbWUsIFRpbWUuZGVzYywgbGVnZW5kX2xhYmVsKSAlPiUgdW5pcXVlICgpICU+JQogICBsZWZ0X2pvaW4oYWVzX2x1dFssIGMoIkNpdHkiLCAiY29scyIpXSwgYnkgPSAiQ2l0eSIpICU+JSB1bmdyb3VwICgpICU+JSB1bmlxdWUgKCklPiUKICAgbGVmdF9qb2luICh0aW1lcywgYnkgPSAiVGltZS5kZXNjIikgJT4lIAogICBhcnJhbmdlKGRhdGF0eXBlLCBDaXR5LCBUcmFpbl9UZXN0LCBUaW1lKSAgICAlPiUgCiAgIG11dGF0ZShhbHBoYSA9IGlmX2Vsc2UoQ2l0eSA9PSAiSG9yc2hhbSIsIGFscGhhLzIsIGFscGhhKSkgJT4lICMgb3RoZXJ3aXNlIHRvbyBkYXJrIHdpdGggdGhpcyBjb2xvcgogIG11dGF0ZV9pZihpcy5mYWN0b3IsIGFzLmNoYXJhY3RlcikgCgpgYGAKCgojIyBEZWNhdHVyIGJveHBsb3RzCgpDaGFuZ2VkIGdyZXkgc3RhcnQgdG8gMSBpbnN0ZWFkIG9mIDAuOCwgZW5kIGF0IDAuNiBpbnN0ZWFkIG9mIDAuNC4KQ2hhbmdlZCBzaGFwZSBvZiBzeW1ib2xzIHNvIHRoZXkgYXJlIGZpbGxlZC4KCmBgYHtyIGRvLW11bHRpY2hlY2stZGVjYXR1ciwgY2FjaGUgPSBUUlVFLCBmaWcud2lkdGg9Ni41LCBmaWcuaGVpZ2h0PTMuNSxkcGk9NjAwfQojI0VGCgpkZl9kZWNhdCAgPC0gZGZfY2hlY2sgJT4lICAgCiAgZmlsdGVyKENpdHkgPT0gIkRlY2F0dXIiICYgVHJhaW5fVGVzdCAlaW4lIGMgKCJUcmFpbiIsICJUZXN0IikpICU+JSAKICBtdXRhdGUocGFuZWwgPSBvcmRlcmVkIChUcmFpbl9UZXN0LCBsZXZlbHMgPSBjICgiVHJhaW4iLCAiVGVzdCIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJFOiBQRk5BIERlY2F0dXIgVHJhaW4iLCAiRjogUEZOQSBEZWNhdHVyIFRlc3QiKSApKQoKYWVzX2x1dF9kZl9kZl9kZWNhdCA8LSBhZXNfbHV0ICU+JSAKICBmaWx0ZXIoQ2l0eSA9PSAiRGVjYXR1ciIgJiBUcmFpbl9UZXN0ICVpbiUgYyAoIlRyYWluIiwgIlRlc3QiKSkgJT4lIAogIG11dGF0ZV9pZihpcy5mYWN0b3IsIGFzLmNoYXJhY3RlcikgCgpzb3VyY2UoIHBhc3RlMChnc3ViKGJhc2VuYW1lKGhlcmUoKSksICdzaGFyZWRfZnVuY3Rpb25zJywgaGVyZSgpKSwgJy9wbG90X3N1bV9ib3hwbG90LnInKSkKCgpwbHRfdHJhaW4gPC0gcGxvdF9zdW1fYm94cGxvdCAgIChkZnJhbWUgPSBkZl9kZWNhdCwgYWVzX2x1dD0gYWVzX2x1dF9kZl9kZl9kZWNhdCwgZmFjZXRzID0gVFJVRSAsIHBmYXNfbm9tID0gcGZhc19uYW1lICAgICApIApwcmludChwbHRfdHJhaW4pCmdnc2F2ZShoZXJlICgib3V0cHV0LXBsb3RzIixwYXN0ZTAoIHNhLCJEZWNhdHVyVHJhaW5UZXN0Ym94cGxvdCIscGZhc19uYW1lLCIucGRmIikpLHBsdF90cmFpbixkcGk9NjAwKQoKCmBgYAoKIyMgQWxsIGJveHBsb3RzCgpDaGFuZ2VkIGdyZXkgc3RhcnQgdG8gMSBpbnN0ZWFkIG9mIDAuOCwgZW5kIGF0IDAuNiBpbnN0ZWFkIG9mIDAuNC4KQWRkZWQgc2hhcGVzIGFuZCBmaWxscyB0byBkYXRhIHBvaW50cy4KCmBgYHtyIGRvLW11bHRpY2hlY2stYWxsLCBjYWNoZSA9IFRSVUUsIGZpZy53aWR0aD02LjUsIGZpZy5oZWlnaHQ9My41LGRwaT02MDB9CgpsZXRzIDwtIExFVFRFUlM7Cm5hbWVzKGxldHMpWzE6KGxlbmd0aCh1bmlxdWUoZGZfY2hlY2skZGF0YXNldCkpLTQpXTwtYXMuY2hhcmFjdGVyKHVuaXF1ZShkZl9jaGVjayRkYXRhc2V0KSlbNTpsZW5ndGgodW5pcXVlKGRmX2NoZWNrJGRhdGFzZXQpKV0KCmZvciAoZCBpbiB1bmlxdWUoZGZfY2hlY2skZGF0YXNldCkpIHsgIyBkID0gdW5pcXVlKGRmX2NoZWNrJGRhdGFzZXQpWzExXQogICAgZGRzZXQgPC0gZGZfY2hlY2sgJT4lICAgIAogICAgZmlsdGVyKGRhdGFzZXQgPT0gZCkgCiAgICAKICAgIGFlc19sdXRfZGRzZXQgPC0gZGRzZXQgJT4lIHNlbGVjdChsZWdlbmRfbGFiZWwsICBDaXR5LFRyYWluX1Rlc3QsZGF0YXR5cGUsIFRpbWUuZGVzYyAgKSAlPiUgdW5pcXVlICgpICU+JSBpbm5lcl9qb2luKGFlc19sdXQpCiAgICAgIAogICAgZ3QgPC0gaWZlbHNlKGlzLm5hKGxldHNbZF0pLGQscGFzdGUwKGxldHNbZF0sIjogIiwgZCkpCiAgICBwbHQgPC0gcGxvdF9zdW1fYm94cGxvdChkZnJhbWUgPSBkZHNldCwgYWVzX2x1dD0gYWVzX2x1dF9kZHNldCwgZ3RpdGxlPSBndCwgZmFjZXRzID0gRkFMU0UsIHBmYXNfbm9tID0gcGZhc19uYW1lKQogICAgIAogIHByaW50KHBsdCkKICBnZ3NhdmUoaGVyZSAoIm91dHB1dC1wbG90cyIsCiAgICAgICAgICAgICAgICBwYXN0ZTAoIHNhLCBkLCItYm94cGxvdC0iLCAKICAgICAgICAgICAgICAgIHBmYXNfbmFtZSwiLnBkZiIpKSAsCiAgICAgICAgIHBsdCxkcGk9NjAwKQoKfQoKIyMjIG1ha2UgVHJhaW5pbmcgcGxvdCAgCgpkZl9kX3RydCA8LSBkZl9jaGVjayAlPiUgICAKICAgICBmaWx0ZXIoIChUcmFpbl9UZXN0ID09ICJUcmFpbiIpICYgKChPdXRwdXRfVmFyID09ICJNX0NiZ2RfQ3NzIikgfCAoT3V0cHV0X1ZhciA9PSAiTV9Dc2VydW0iKSkpICU+JQogICAgIG11dGF0ZV9pZihpcy5mYWN0b3IsIGFzLmNoYXJhY3RlcikgJT4lICAjIGRyb3AgZmFjdG9yIGxldmVscyB1bnVzZWQKICAgICBtdXRhdGUoRGF0YXNldC5UaW1lID0gZmFjdG9yKERhdGFzZXQuVGltZSkpIAogCgogYWVzX2x1dF9kZl9kX3RydCA8LSAgZGZfZF90cnQgJT4lIHNlbGVjdChDaXR5LCBkYXRhdHlwZSxUaW1lLCBUaW1lLmRlc2MsIGxlZ2VuZF9sYWJlbCkgJT4lIAogICBpbm5lcl9qb2luKGFlc19sdXQgICkgJT4lIAogICBzZWxlY3QoLVRyYWluX1Rlc3QpICU+JSB1bmdyb3VwICgpICU+JSB1bmlxdWUgKCkgIAoKcGx0X3RyYWluIDwtICAgIHBsb3Rfc3VtX2JveHBsb3QoZGZyYW1lID0gZGZfZF90cnQsIGFlc19sdXQ9IGFlc19sdXRfZGZfZF90cnQsICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd0aXRsZT0iQTogU3VtbWFyeSBEYXRhIC0gVHJhaW4iICwgZmFjZXRzID0gRkFMU0UsIHBmYXNfbm9tID0gcGZhc19uYW1lICkKICBwcmludChwbHRfdHJhaW4pCiAgZ2dzYXZlKGhlcmUgKCJvdXRwdXQtcGxvdHMiLCBwYXN0ZTAoIHNhLCAiU3VtbWFyeVRyYWluRGF0YWJveHBsb3QiLHBmYXNfbmFtZSwiLnBkZiIpKSwgcGx0X3RyYWluLGRwaT02MDApCgojIyMgIG1ha2UgVGVzdCBwbG90CmRmX2RfdGVzdCA8LSBkZl9jaGVjayAlPiUgICAKICAgIGZpbHRlcigoVHJhaW5fVGVzdCA9PSAiVGVzdCIpICYgCiAgICAgICAgICAgICAoKE91dHB1dF9WYXIgPT0gIk1fQ2JnZF9Dc3MiKSB8IChPdXRwdXRfVmFyID09ICJNX0NzZXJ1bSIpKSkgICU+JQogICAgIG11dGF0ZV9pZihpcy5mYWN0b3IsIGFzLmNoYXJhY3RlcikgJT4lICAjIGRyb3AgZmFjdG9yIGxldmVscyB1bnVzZWQKICAgICBtdXRhdGUoRGF0YXNldC5UaW1lID0gZmFjdG9yKERhdGFzZXQuVGltZSkpIAoKYWVzX2x1dF9kZl9kX3Rlc3QgPC0gIGRmX2RfdGVzdCAlPiUgc2VsZWN0KENpdHksIGRhdGF0eXBlLFRpbWUsIFRpbWUuZGVzYywgbGVnZW5kX2xhYmVsKSAlPiUgCiAgIGlubmVyX2pvaW4oYWVzX2x1dCAgKSAlPiUgCiAgIHNlbGVjdCgtVHJhaW5fVGVzdCkgJT4lIHVuZ3JvdXAgKCkgJT4lIHVuaXF1ZSAoKSAgCgpwbHRfdGVzdCA8LSBwbG90X3N1bV9ib3hwbG90KGRmcmFtZSA9IGRmX2RfdGVzdCwgYWVzX2x1dD0gYWVzX2x1dF9kZl9kX3Rlc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd0aXRsZT0iQjogU3VtbWFyeSBEYXRhIC0gVGVzdCIsIGZhY2V0cyA9IEZBTFNFLCBwZmFzX25vbSA9IHBmYXNfbmFtZSkKICBwcmludChwbHRfdGVzdCkKICBnZ3NhdmUoaGVyZSAoIm91dHB1dC1wbG90cyIscGFzdGUwKCBzYSwgIlN1bW1hcnlUZXN0RGF0YWJveHBsb3QiLHBmYXNfbmFtZSwiLnBkZiIpKSwgcGx0X3Rlc3QsZHBpPTYwMCkgIApgYGAKCiMjIFBGTkEKIyMjIEJhY2tncm91bmQgcG9zdGVyaW9ycwoKU2hvd3Mgc2hpZnQgaW4gYmFja2dyb3VuZCBlc3RpbWF0ZS4KCmBgYHtyIGdldCBiYWNrZ3JvdW5kLCBjYWNoZSA9IFRSVUUsZmlnLmhlaWdodD02LGZpZy53aWR0aD01LGRwaT02MDB9CgpnbXNjYWxlPC0wLjgKCmRhdCA8LSBtdWx0aWNoZWNrJHBhcm1zLnNhbXBbLGdyZXAoIk1fbG5fQ2JnZCIsbmFtZXMobXVsdGljaGVjayRwYXJtcy5zYW1wKSldCmRhdGFzZXRuYW1lcyA8LSBhcy5jaGFyYWN0ZXIodW5pcXVlKGNhbGliZGF0YSRkYXRhc2V0KSkKZGF0YXNldG5hbWVzIDwtIGdzdWIoIiBUcmFpbiIsIi1UcmFpbiIsZGF0YXNldG5hbWVzKQpkYXRhc2V0bmFtZXMgPC0gZ3N1YigiIFRlc3QiLCItVHJhaW4iLGRhdGFzZXRuYW1lcykKZGF0YXNldG5hbWVzIDwtIGdzdWIoIiBNIiwiIixkYXRhc2V0bmFtZXMpCmRhdGFzZXRuYW1lcyA8LSBnc3ViKCIgRiIsIiIsZGF0YXNldG5hbWVzKQpkYXRhc2V0bmFtZXM8LWRhdGFzZXRuYW1lc1shZHVwbGljYXRlZChkYXRhc2V0bmFtZXMpXQpuYW1lcyhkYXQpIDwtIGRhdGFzZXRuYW1lcwpkYXQgPC0gZGF0WyxncmVwKCJUcmFpbiIsbmFtZXMoZGF0KSldCmRhdC5kZiA8LSBwaXZvdF9sb25nZXIoZGF0LDE6bmNvbChkYXQpKQpkYXQuZGYgPC0gcmJpbmQoZGF0LmRmLAogICAgICAgICAgICAgICAgZGF0YS5mcmFtZShuYW1lPSJQcmlvciIsdmFsdWU9cm5vcm0oNTAwMCxtPWxvZyhnbXNjYWxlKSxzZD0wLjQwNTUpKSkKZGF0LmRmJG5hbWUgPC0gZmFjdG9yKGRhdC5kZiRuYW1lLGxldmVscz1yZXYoCiAgICAgICAgICAgICAgICAgICAgICAgIGMoIlByaW9yIixkYXRhc2V0bmFtZXNbZ3JlcCgiVHJhaW4iLGRhdGFzZXRuYW1lcyldKSkpCmRhdC5kZiR2YWx1ZSA8LSBleHAoZGF0LmRmJHZhbHVlKQoKcDwtZ2dwbG90KGRhdC5kZikrCiAgI2dlb21fdmlvbGluKGFlcyh4PW5hbWUseT12YWx1ZSxmaWxsPW5hbWU9PSJQcmlvciIpKSsKICBnZW9tX2JveHBsb3QoYWVzKHg9bmFtZSx5PXZhbHVlLGZpbGw9bmFtZT09IlByaW9yIiksb3V0bGllci5zaGFwZT1OQSkrCiAgc2NhbGVfeV9sb2cxMCgpK2Nvb3JkX2ZsaXAoKSsKICAgICAgc2NhbGVfZmlsbF9tYW51YWwobmFtZT1OVUxMLCAKICAgICAgICAgICAgICAgICAgICB2YWx1ZXM9YygiIzAwOTk4OCIsICIjRUU3NzMzIiApKSsKICB0aGVtZV9jbGFzc2ljKCkgKyAgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gZ21zY2FsZSxjb2xvcj0iZ3JleSIpKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIsCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3I9ImJsYWNrIixzaXplPTEpKSsKICB5bGFiKCJQb3N0ZXJpb3Igc2hpZnQgaW4gQmFja2dyb3VuZCBDb25jZW50cmF0aW9uIikKCnByaW50KHApCmdnc2F2ZShoZXJlICgib3V0cHV0LXBsb3RzIixwYXN0ZTAoIHNhLCAiUEZOQV9HTV9DYmdkLnBkZiIpKSAscCxkcGk9NjAwKQoKYGBgCgoKIyMjIEhhbGYtbGlmZQoKRm9yIFBGTkEsIHRoZSBwb3B1bGF0aW9uIEdNIG9mIHRoZSBoYWxmLWxpZmUgaGFzIGEgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiB0aGF0IGlzIG5hcnJvd2VyIHRoYW4gdGhlIHByaW9yLCB3aXRoIGEgcG9zdGVyaW9yIG1lZGlhbiAoOTUlIENJKSBlc3RpbWF0ZSBvZiAzLjA2ICgyLjE2LTQuMzcpIHllYXJzLiBUaGUgcG9wdWxhdGlvbiBHU0QgcG9zdGVyaW9yIGlzIGxhcmdlciB0aGFuIHRoZSBwcmlvciBhdCAxLjQ3KDEuNDQtMS43NSkuCgpgYGB7ciBwb3N0ZXJpb3IgaGlzdG9ncmFtcywgY2FjaGUgPSBUUlVFfQoKZGF0IDwtIG11bHRpY2hlY2skcGFybXMuc2FtcFssYygiTV9sbl9rLjEuIiwiVl9sbl9rLjEuIiwgIk1fbG5fVmQuMS4iLCAiU0RfbG5fVmQuMS4iKV0KbmFtZXMoZGF0KSA8LSBjKCJNX2xuX2soMSkiLCJWX2xuX2soMSkiLCAiTV9sbl9WZCgxKSIsICJTRF9sbl9WZCgxKSIpCiAgCnNldC5zZWVkKDMuMTQxNTkpCmRhdCR6X2xuX2sgPC0gcm5vcm0obnJvdyhkYXQpKQpkYXQkel9sbl9WZCA8LSBybm9ybShucm93KGRhdCkpCmRhdCAlPiUgcmVuYW1lXygpCmRhdCRsbl9rX2kgPC0gZGF0JGBNX2xuX2soMSlgICsgc3FydChkYXQkYFZfbG5faygxKWApKmRhdCR6X2xuX2sKZGF0JGxuX1ZkX2kgPC0gZGF0JGBNX2xuX1ZkKDEpYCsgZGF0JGBTRF9sbl9WZCgxKWAqZGF0JHpfbG5fVmQKbGlubW9kIDwtIGxtKGxuX1ZkX2kgfiBsbl9rX2ksZGF0YT1kYXQpCmdncGxvdChkYXQpICsgZ2VvbV9wb2ludChhZXMobG5fa19pLGxuX1ZkX2kpKSArIAogIGxhYnMoc3VidGl0bGU9cGFzdGUoIkFkaiBSMiA9IixzaWduaWYoc3VtbWFyeShsaW5tb2QpJGFkai5yLnNxdWFyZWQsMikpKQpgYGAKCgojIyBDaGVjayBub3JtYWxpdHkKCmBgYHtyIG5vcm1hbGl0eSwgY2FjaGUgPSBUUlVFfQoKcXFub3JtKGRhdCRsbl9rX2ksbWFpbj0ibG4gayBRLVEgTm9ybWFsIikKcXFsaW5lKGRhdCRsbl9rX2ksY29sPSJyZWQiKQpwbG90KGVjZGYoZGF0JGxuX2tfaSkpCnggPC0gc2VxKC0zLDEsMC4wMSkKbV9sbl9rX2kgPC0gICBtZWFuKGRhdCRsbl9rX2kpCnNkX2xuX2tfaSA8LSBzZChkYXQkbG5fa19pKQpsaW5lcyh4LHBub3JtKHgsbWVhbj1tX2xuX2tfaSxzZD1zZF9sbl9rX2kpLGNvbD0icmVkIikKdGV4dChtX2xuX2tfaS0yKnNkX2xuX2tfaSwwLjkscGFzdGUoIm0gPSIsc2lnbmlmKG1fbG5fa19pLDQpLCJcbnNkID0iLHNpZ25pZihzZF9sbl9rX2ksNCkpKQoKcXFub3JtKGRhdCRsbl9WZF9pLG1haW49ImxuIFZkIFEtUSBOb3JtYWwiKQpxcWxpbmUoZGF0JGxuX1ZkX2ksY29sPSJyZWQiKQpwbG90KGVjZGYoZGF0JGxuX1ZkX2kpKQp4IDwtIHNlcSgtMywxLDAuMDEpCm1fbG5fVmRfaSA8LSBtZWFuKGRhdCRsbl9WZF9pKQpzZF9sbl9WZF9pIDwtIHNkKGRhdCRsbl9WZF9pKQoKbGluZXMoeCxwbm9ybSh4LG1lYW49bV9sbl9WZF9pLHNkPXNkX2xuX1ZkX2kpLGNvbD0icmVkIikKdGV4dChtX2xuX1ZkX2ktMipzZF9sbl9WZF9pLDAuOSxwYXN0ZSgibSA9IixzaWduaWYobV9sbl9WZF9pLDQpLCJcbnNkID0iLHNpZ25pZihzZF9sbl9WZF9pLDQpKSkKCmBgYAoKIyMgQ2FsY3VsYXRlIHRhYmxlIHZhbHVlcyBmb3IgaW5kaXZpZHVhbC1sZXZlbApgYGB7ciBtYWtlLWluZGl2aWR1YWwtcGFyYW0tb3V0LCBjYWNoZSA9IFRSVUV9CmhsX2kgPC0gbG9nKDIpLyBleHAoZGF0JGxuX2tfaSkgIyBpbmRpdmlkdWFsIGhhbGYtbGlmZSAKbWVkX2hsX2kgPC0gcGFzdGUoc2lnbmlmIChtZWRpYW4gKGhsX2kpLCAzKSkgIyBtZWRpYW4gb2YgaW5kaXZpZHVhbCBoYWxmLWxpZmUKY2lfbWVkX2hsX2kgPC0gICBwYXN0ZShzaWduaWYgKHF1YW50aWxlKGhsX2ksIHByb2I9YygwLjAyNSwwLjk3NSkpLCAzKSxjb2xsYXBzZT0iLSIpICMgOTVjaSBtZWQgaW5kaXZpZHVhbCBoYWxmbGlmZQpjaTk4X21lZF9obF9pIDwtICAgcGFzdGUoc2lnbmlmIChxdWFudGlsZShobF9pLCBwcm9iPWMoMC4wMSwwLjk5KSksIDMpLGNvbGxhcHNlPSItIikgIyA5OGNpIG1lZCBpbmRpdmlkdWFsIGhhbGZsaWZlCmdtX2hsX2kgPC0gcGFzdGUoc2lnbmlmIChleHAobWVhbihsb2coaGxfaSkpKSwgMykpICMgZ20gKHdoaWNoIHNob3VsZCBiZSByZWFsbHkgY2xvc2UpCmdzZF9obF9pIDwtIHBhc3RlKHNpZ25pZiAoZXhwKHNkKGxvZyhobF9pKSkpLCAzKSkgIyBnc2QgaW5kaXZpZHVhbAoKbWVkX1ZkX2kgPC0gcGFzdGUoc2lnbmlmIChtZWRpYW4oZXhwKGRhdCRsbl9WZF9pKSksIDMpKSAjIG1lZGlhbiBpbmRpdmlkdWFsIFZkCmNpX21lZF9WZF9pIDwtcGFzdGUoc2lnbmlmIChxdWFudGlsZShleHAoZGF0JGxuX1ZkX2kpLCBwcm9iPWMoMC4wMjUsMC45NzUpKSwgMyksY29sbGFwc2U9Ii0iKSAjIDk1Y2kgbWVkIGluZGl2aWR1YWwgVmQKY2k5OF9tZWRfVmRfaSA8LXBhc3RlKHNpZ25pZiAocXVhbnRpbGUoZXhwKGRhdCRsbl9WZF9pKSwgcHJvYj1jKDAuMDEsMC45OSkpLCAzKSxjb2xsYXBzZT0iLSIpICMgOThjaSBtZWQgaW5kaXZpZHVhbCBWZApnbV92ZF9pIDwtIHBhc3RlKHNpZ25pZiAoZXhwKG1lYW4oZGF0JGxuX1ZkX2kpKSwgMykpICMgZ20gKHdoaWNoIHNob3VsZCBiZSByZWFsbHkgY2xvc2UpCmdzZF92ZF9pPC0gcGFzdGUoc2lnbmlmIChleHAoc2QoZGF0JGxuX1ZkX2kpKSwgMykpICMgZ3NkIGluZGl2CmBgYAoKCmBgYHtyIGhhbGYtbGlmZSxmaWcuaGVpZ2h0PTIuNSxmaWcud2lkdGg9NCxkcGk9NjAwfQpQRk5BX3ByaW9ycyA8LSBkYXRhLmZyYW1lKAogIGhhbGZsaWZlX0dNPSBsb2coMikvcmxub3JtKDUwMDAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW5sb2c9LTEuODAxODEsc2Rsb2c9MC40MDU1KSkKTV9rIDwtIGV4cChhcy5udW1lcmljKGRhdCRgTV9sbl9rKDEpYCkpClBGTkFfaGFsZmxpZmVfR00gPC0gbG9nKDIpL01fawoKUEZOQV9obGdtX3ByX21lZCA8LSBzaWduaWYobWVkaWFuKFBGTkFfcHJpb3JzJGhhbGZsaWZlX0dNLDMpKQpQRk5BX2hsZ21fcHJfbWVkXzk1Y2kgPC1wYXN0ZShzaWduaWYocXVhbnRpbGUoUEZOQV9wcmlvcnMkaGFsZmxpZmVfR00sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYj1jKDAuMDI1LDAuOTc1KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZT0iLSIpCgpQRk5BX2hsX21lZGlhbl9nbSA8LSBzaWduaWYobWVkaWFuKFBGTkFfaGFsZmxpZmVfR00pLDMpClBGTkFfaGxfbWVkaWFuX2dtXzk1Y2kgPC0gcGFzdGUoc2lnbmlmKHF1YW50aWxlKFBGTkFfaGFsZmxpZmVfR00sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYj1jKDAuMDI1LDAuOTc1KSksMyksY29sbGFwc2U9Ii0iKQoKcDwtZ2dwbG90KCkrCiAgc3RhdF9kZW5zaXR5KGFlcyhoYWxmbGlmZV9HTSwgY29sb3IgPSAiUHJpb3IiKSxkYXRhPVBGTkFfcHJpb3JzLGdlb209ImxpbmUiLHNpemU9MikrCiAgc3RhdF9kZW5zaXR5KGFlcyhQRk5BX2hhbGZsaWZlX0dNLHN0YXQoZGVuc2l0eSksY29sb3I9IlBvc3RlcmlvciIpLGdlb209ImxpbmUiLHNpemU9MS41KSsKICB4bGltKDAsMTUpKwogIGxhYnModGl0bGUgPSBicXVvdGUoIkU6IFBGTkEiflRbMS8yXX4iUG9wdWxhdGlvbiBHTSIpICAsCiAgICAgICBzdWJ0aXRsZT1wYXN0ZSgiUG9zdGVyaW9yIE1lZGlhbiAoOTUlIENJKTogIiwKICAgICAgICAgICAgICAgICAgICAgIFBGTkFfaGxfbWVkaWFuX2dtLCIgKCIsCiAgICAgICAgICAgICAgICAgICAgICBQRk5BX2hsX21lZGlhbl9nbV85NWNpLAogICAgICAgICAgICAgICAgICAgICAgIikiLHNlcD0iIikpKwogeGxhYihicXVvdGUoIlBvcHVsYXRpb24gR00iflRbMS8yXX4iKHlycykiKSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lPU5VTEwsIAogICAgICAgICAgICAgICAgICAgICB2YWx1ZXM9YyhQcmlvcj0iIzAwOTk4OCIsIFBvc3Rlcmlvcj0iI0VFNzczMyIgKSkgKyAKICB0aGVtZV9jbGFzc2ljKCkgKyAgCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLGxlZ2VuZC5wb3NpdGlvbj1jKDAuOCwwLjcpLAogICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yPSJibGFjayIsc2l6ZT0xKSwKICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvcj1OQSkpCnByaW50KHApCmdnc2F2ZShoZXJlICgib3V0cHV0LXBsb3RzIiwgcGFzdGUwKCBzYSwgIlBGTkFfaGxfZ20ucGRmIikpICxwLGRwaT02MDApCiAKYGBgCgoKCmBgYHtyIFBGTkEtaGFsZi1saWZlLWdzZCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSxmaWcuaGVpZ2h0PTIuNSxmaWcud2lkdGg9NCxkcGk9NjAwfQpQRk5BX3ByaW9ycyRoYWxmbGlmZV9HU0QgPSAgZXhwKHNxcnQoZXhwKHJub3JtKDUwMDAwLG09bG9nKDAuMjAwMCksc2Q9bG9nKDEuMjc1KSkpKSkgClBGTkFfaGFsZmxpZmVfR1NEIDwtIGV4cChzcXJ0KGRhdCRgVl9sbl9rKDEpYCkpCgpQRk5BX2hsZ3NkX3ByX21lZCA8LSBzaWduaWYobWVkaWFuKFBGTkFfcHJpb3JzJGhhbGZsaWZlX0dTRCwzKSkKUEZOQV9obGdzZF9wcl9tZWRfOTVjaSA8LXBhc3RlKHNpZ25pZihxdWFudGlsZShQRk5BX3ByaW9ycyRoYWxmbGlmZV9HU0QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYj1jKDAuMDI1LDAuOTc1KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZT0iLSIpClBGTkFfaGxfZ3NkX21lZCA8LSBzaWduaWYobWVkaWFuKFBGTkFfaGFsZmxpZmVfR1NEKSwzKQpQRk5BX2hsX2dzZF9tZWRfOTVjaSA8LSBwYXN0ZShzaWduaWYocXVhbnRpbGUoUEZOQV9oYWxmbGlmZV9HU0QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYj1jKDAuMDI1LDAuOTc1KSksMyksY29sbGFwc2U9Ii0iKQpwPC1nZ3Bsb3QoKSsKICBzdGF0X2RlbnNpdHkoYWVzKGhhbGZsaWZlX0dTRCwgY29sb3IgPSAiUHJpb3IiKSxkYXRhPVBGTkFfcHJpb3JzLGdlb209ImxpbmUiLHNpemU9MikrCiAgc3RhdF9kZW5zaXR5KGFlcyhQRk5BX2hhbGZsaWZlX0dTRCxzdGF0KGRlbnNpdHkpLCBjb2xvciA9ICJQb3N0ZXJpb3IiKSxnZW9tPSJsaW5lIixzaXplPTEuNSkrCiAgeGxpbSgxLDMpKwogIGxhYnModGl0bGUgPSBicXVvdGUoIkY6IFBGTkEiflRbMS8yXX4iUG9wdWxhdGlvbiBHU0QiKSwgCiAgICAgICBzdWJ0aXRsZT1wYXN0ZSgiUG9zdGVyaW9yIE1lZGlhbiAoOTUlIENJKTogIiwKICAgICAgICAgICAgICAgICAgICAgIFBGTkFfaGxfZ3NkX21lZCwiICgiLAogICAgICAgICAgICAgICAgICAgICAgUEZOQV9obF9nc2RfbWVkXzk1Y2ksCiAgICAgICAgICAgICAgICAgICAgICAiKSIsc2VwPSIiKSkrCiAgeGxhYihicXVvdGUoIlBvcHVsYXRpb24gR1NEIn5UWzEvMl0pKSsKICBzY2FsZV9jb2xvcl9tYW51YWwobmFtZT1OVUxMLCAKICAgICAgICAgICAgICAgICAgICAgdmFsdWVzPWMoUHJpb3I9IiMwMDk5ODgiLCBQb3N0ZXJpb3I9IiNFRTc3MzMiICkpICsgCiAgIHRoZW1lX2NsYXNzaWMoKSArICAKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksbGVnZW5kLnBvc2l0aW9uPWMoMC44LDAuNyksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3I9ImJsYWNrIixzaXplPTEpLAogICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG9yPU5BKSkKcHJpbnQocCkKZ2dzYXZlKGhlcmUgKCJvdXRwdXQtcGxvdHMiLCBwYXN0ZTAoIHNhLCAiUEZOQV9obF9nc2QucGRmIikpLCBwLGRwaT02MDApCgpgYGAKCgojIyMgRGlzdHJpYnV0aW9uIFZvbHVtZQpGb3IgUEZOQSwgdGhlIGRhdGEgd2VyZSBub3QgcGFydGljdWxhcmx5IGluZm9ybWF0aXZlLCBidXQgc2xpZ2h0bHkgaW5jcmVhc2VkIHRoZSBlc3RpbWF0ZSBvZiB0aGUgbWVkaWFuIHRvIDAuMzA4KDAuMjIzLTAuNTQ4KSBzbGlnaHRseS4gVGhleSB3ZXJlIG5vdCBpbmZvcm1hdGl2ZSBhcyB0byB0aGUgcG9wdWxhdGlvbiBHU0QsIHdpdGggdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb25zIGVzc2VudGlhbGx5IHVuY2hhbmdlZCBmcm9tIHRoZSBwcmlvcnMuCmBgYHtyIFBGTkEtdmQtZ20sIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsZmlnLmhlaWdodD0yLjUsZmlnLndpZHRoPTQsZHBpPTYwMH0KUEZOQV9wcmlvcnMkVmRfR00gPC0gcmxub3JtKDUwMDAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lYW5sb2c9LTEuNzcxOTYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Rsb2c9MC4yNjI0KQpQRk5BX1ZkX0dNIDwtIGV4cChkYXQkYE1fbG5fVmQoMSlgKQoKIAoKUEZOQV92ZF9nbV9wcl9tZWQgPC0gc2lnbmlmKG1lZGlhbihQRk5BX3ByaW9ycyRWZF9HTSwzKSkKUEZOQV92ZF9nbV9wcl9tZWRfOTVjaSA8LSBwYXN0ZShzaWduaWYocXVhbnRpbGUoUEZOQV9wcmlvcnMkVmRfR00sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYj1jKDAuMDI1LDAuOTc1KSksIDMpLCBjb2xsYXBzZT0iLSIpClBGTkFfdmRfZ21fbWVkIDwtIHNpZ25pZihtZWRpYW4oUEZOQV9WZF9HTSksMykKUEZOQV92ZF9nbV9tZWRfOTVjaSA8LSBwYXN0ZShzaWduaWYocXVhbnRpbGUoUEZOQV9WZF9HTSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9iPWMoMC4wMjUsMC45NzUpKSwzKSxjb2xsYXBzZT0iLSIpCgpwPC1nZ3Bsb3QoKSsKICBzdGF0X2RlbnNpdHkoYWVzKFZkX0dNLCBjb2xvciA9ICJQcmlvciIpLGRhdGE9UEZOQV9wcmlvcnMsZ2VvbT0ibGluZSIsc2l6ZT0yKSsKICBzdGF0X2RlbnNpdHkoYWVzKFBGTkFfVmRfR00sc3RhdChkZW5zaXR5KSwgY29sb3IgPSAiUG9zdGVyaW9yIiksZ2VvbT0ibGluZSIsc2l6ZT0xLjUpKwogIHhsaW0oMCwxKStsYWJzKHRpdGxlID0gYnF1b3RlKCJFOiBQRk5BIn5WW2RdfiJQb3B1bGF0aW9uIEdNIiksCiAgICAgICAgICAgICAgICAgc3VidGl0bGU9cGFzdGUoIlBvc3RlcmlvciBNZWRpYW4gKDk1JSBDSSk6ICIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUEZOQV92ZF9nbV9tZWQsIiAoIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUEZOQV92ZF9nbV9tZWRfOTVjaSwiKSIsc2VwPSIiKSkrCiAgIHhsYWIoYnF1b3RlKCJQb3B1bGF0aW9uIEdNIn5WW2RdfiIobC9rZykiKSkrCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWU9TlVMTCwgCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcz1jKFByaW9yPSIjMDA5OTg4IiwgUG9zdGVyaW9yPSIjRUU3NzMzIiApKSAgICsgIAogIHRoZW1lX2NsYXNzaWMoKSArICAKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksbGVnZW5kLnBvc2l0aW9uPWMoMC44LDAuNyksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3I9ImJsYWNrIixzaXplPTEpLAogICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG9yPU5BKSkKcHJpbnQocCkKZ2dzYXZlKGhlcmUgKCJvdXRwdXQtcGxvdHMiLHBhc3RlMCggc2EsICJQRk5BX3ZkX2dtLnBkZiIpKSwgcCxkcGk9NjAwKQoKYGBgCgoKYGBge3IgUEZOQS12ZC1zZCwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSxmaWcuaGVpZ2h0PTIuNSxmaWcud2lkdGg9NCxkcGk9NjAwfQpQRk5BX3ByaW9ycyRWZF9HU0QgPSBleHAoYWJzKHJub3JtKDUwMDAwLHNkPTAuMTcpKSkKUEZOQV9WZF9HU0QgPC0gZXhwKGRhdCRgU0RfbG5fVmQoMSlgKQoKUEZOQV92ZF9nc2RfcHJfbWVkIDwtIHNpZ25pZihtZWRpYW4oUEZOQV9wcmlvcnMkVmRfR1NELDMpKQpQRk5BX3ZkX2dzZF9wcl9tZWRfOTVjaSA8LSBwYXN0ZShzaWduaWYocXVhbnRpbGUoUEZOQV9wcmlvcnMkVmRfR1NELAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2I9YygwLjAyNSwwLjk3NSkpLCAzKSwgY29sbGFwc2U9Ii0iKQoKUEZOQV92ZF9nc2RfbWVkIDwtIHNpZ25pZihtZWRpYW4oUEZOQV9WZF9HU0QpLDMpClBGTkFfdmRfZ3NkX21lZF85NWNpIDwtIHBhc3RlKHNpZ25pZihxdWFudGlsZShQRk5BX1ZkX0dTRCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9iPWMoMC4wMjUsMC45NzUpKSwzKSxjb2xsYXBzZT0iLSIpCgpwPC1nZ3Bsb3QoKSsKICBzdGF0X2RlbnNpdHkoYWVzKFZkX0dTRCwgY29sb3IgPSAiUHJpb3IiKSxkYXRhPVBGTkFfcHJpb3JzLGdlb209ImxpbmUiLHNpemU9MikrCiAgc3RhdF9kZW5zaXR5KGFlcyhQRk5BX1ZkX0dTRCxzdGF0KGRlbnNpdHkpLCBjb2xvciA9ICJQb3N0ZXJpb3IiKSxnZW9tPSJsaW5lIixzaXplPTEuNSkrCiAgeGxpbSgxLDMpKwogIGxhYnModGl0bGUgPSBicXVvdGUoIkY6IFBGTkEiflZbZF1+IlBvcHVsYXRpb24gR1NEICIpLAogICAgICAgc3VidGl0bGU9cGFzdGUoIlBvc3RlcmlvciBNZWRpYW4gKDk1JSBDSSk6ICIsCiAgICAgICAgICAgICAgICAgICAgICBQRk5BX3ZkX2dzZF9tZWQsIiAoIiwKICAgICAgICAgICAgICAgICAgICAgIFBGTkFfdmRfZ3NkX21lZF85NWNpLAogICAgICAgICAgICAgICAgICAgICAgIikiLHNlcD0iIikpKwogIHhsYWIoYnF1b3RlKCJQb3B1bGF0aW9uIEdTRCJ+VltkXSkpKwogIHNjYWxlX2NvbG9yX21hbnVhbChuYW1lPU5VTEwsIAogICAgICAgICAgICAgICAgICAgICB2YWx1ZXM9YyhQcmlvcj0iIzAwOTk4OCIsIFBvc3Rlcmlvcj0iI0VFNzczMyIgKSkgKyAgCiAgdGhlbWVfY2xhc3NpYygpICsgIAogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSxsZWdlbmQucG9zaXRpb249YygwLjgsMC43KSwKICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvcj0iYmxhY2siLHNpemU9MSksCiAgICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3I9TkEpKQpwcmludChwKQpnZ3NhdmUoaGVyZSAoIm91dHB1dC1wbG90cyIscGFzdGUwKCBzYSwgIlBGTkFfdmRfZ3NkLnBkZiIpKSwgcCxkcGk9NjAwKQoKYGBgCiMjIyBDbGVhcmFuY2UgKGp1c3QgcG9wIEdNKQoKQ2wgaXMgayAqIFZkCgpgYGB7ciBQRk5BLWNsLWdtLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLGZpZy5oZWlnaHQ9Mi41LGZpZy53aWR0aD00LGRwaT02MDB9ClBGTkFfcHJpb3JzJENMX0dNIDwtIFBGTkFfcHJpb3JzJFZkX0dNICogKGxvZygyKS9QRk5BX3ByaW9ycyRoYWxmbGlmZV9HTSkKUEZOQV9DTF9HTSA8LSBleHAoZGF0JGBNX2xuX1ZkKDEpYCArIGRhdCRgTV9sbl9rKDEpYCkKClBGTkFfY2xfZ21fcHJfbWVkIDwtIHNpZ25pZihtZWRpYW4oUEZOQV9wcmlvcnMkQ0xfR00sMykpClBGTkFfY2xfZ21fcHJfbWVkXzk1Y2kgPC0gcGFzdGUoc2lnbmlmKHF1YW50aWxlKFBGTkFfcHJpb3JzJENMX0dNLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2I9YygwLjAyNSwwLjk3NSkpLCAzKSwgY29sbGFwc2U9Ii0iKQpQRk5BX2NsX2dtX21lZCA8LSBzaWduaWYobWVkaWFuKFBGTkFfQ0xfR00pLDMpClBGTkFfY2xfZ21fbWVkXzk1Y2kgPC0gcGFzdGUoc2lnbmlmKHF1YW50aWxlKFBGTkFfQ0xfR00sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYj1jKDAuMDI1LDAuOTc1KSksMyksY29sbGFwc2U9Ii0iKQoKcDwtZ2dwbG90KCkrCiAgc3RhdF9kZW5zaXR5KGFlcyhDTF9HTSwgY29sb3IgPSAiUHJpb3IiKSxkYXRhPVBGTkFfcHJpb3JzLGdlb209ImxpbmUiLHNpemU9MikrCiAgc3RhdF9kZW5zaXR5KGFlcyhQRk5BX0NMX0dNLHN0YXQoZGVuc2l0eSksIGNvbG9yID0gIlBvc3RlcmlvciIpLGdlb209ImxpbmUiLHNpemU9MS41KSsKICB4bGltKDAsMC4yNSkrbGFicyh0aXRsZSA9ICJDOiBQRk5BIENsZWFyYW5jZSBQb3AuIEdNICIsc3VidGl0bGU9cGFzdGUoIlBvc3RlcmlvciBNZWRpYW4gKDk1JSBDSSk6ICIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUEZOQV9jbF9nbV9tZWQsIiAoIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQRk5BX2NsX2dtX21lZF85NWNpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIpIixzZXA9IiIpKSsKICB4bGFiKCJQb3AuIEdNIENMIChsLyhrZy15cikpIikrCiAgc2NhbGVfY29sb3JfbWFudWFsKG5hbWU9TlVMTCwgCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcz1jKFByaW9yPSIjMDA5OTg4IiwgUG9zdGVyaW9yPSIjRUU3NzMzIiApKSArICAKICB0aGVtZV9jbGFzc2ljKCkgKyAgCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLGxlZ2VuZC5wb3NpdGlvbj1jKDAuOCwwLjcpLAogICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yPSJibGFjayIsc2l6ZT0xKSwKICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvcj1OQSkpCnByaW50KHApCmdnc2F2ZShoZXJlICgib3V0cHV0LXBsb3RzIixwYXN0ZTAoIHNhLCAiUEZOQV9DTF9nbS5wZGYiKSkgLHAsZHBpPTYwMCkKCmBgYAoKIyMgVGFibGUgc2lnbmlmaWNhbnQgZGlnaXQgdmFsdWVzCgpgYGB7ciB0YWJsZS12YXJzIH0KUEZOQV9obGdtX3ByX21lZCA8LSBwYXN0ZShzaWduaWYoUEZOQV9obGdtX3ByX21lZCwgMykpClBGTkFfaGxfbWVkaWFuX2dtPC0gcGFzdGUoc2lnbmlmKFBGTkFfaGxfbWVkaWFuX2dtLCAzKSkKUEZOQV9obGdzZF9wcl9tZWQ8LSBwYXN0ZShzaWduaWYoUEZOQV9obGdzZF9wcl9tZWQsIDMpKQpQRk5BX2hsX2dzZF9tZWQ8LSBwYXN0ZShzaWduaWYoUEZOQV9obF9nc2RfbWVkLCAzKSkKUEZOQV92ZF9nbV9wcl9tZWQ8LSBwYXN0ZShzaWduaWYoUEZOQV92ZF9nbV9wcl9tZWQsIDMpKQpQRk5BX3ZkX2dtX21lZDwtIHBhc3RlKHNpZ25pZihQRk5BX3ZkX2dtX21lZCwgMykpClBGTkFfdmRfZ3NkX3ByX21lZDwtIHBhc3RlKHNpZ25pZihQRk5BX3ZkX2dzZF9wcl9tZWQsIDMpKQpQRk5BX3ZkX2dzZF9tZWQ8LSBwYXN0ZShzaWduaWYoUEZOQV92ZF9nc2RfbWVkLCAzKSkKUEZOQV9jbF9nbV9wcl9tZWQ8LSBwYXN0ZShzaWduaWYoUEZOQV9jbF9nbV9wcl9tZWQsIDMpKQpQRk5BX2NsX2dtX21lZDwtIHBhc3RlKHNpZ25pZihQRk5BX2NsX2dtX21lZCwgMykpCmBgYAoKIyMjIFBvcHVsYXRpb24gbWVkaWFuIGVzdGltYXRlcyBbOTUlIENJXSAKCnwgUGFyYW1ldGVyICAgICAgICAgICAgICAgICAgICAgIHwgUHJpb3IgR00gICAgICB8IFBvc3RlcmlvciBHTSB8IFByaW9yICBHU0QgICAgfCBQb3N0ZXJpb3IgR1NEIHwgCnwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tOnwgCnwgSGFsZi1saWZlICh5ZWFycykgIHwgYHIgcGFzdGUoUEZOQV9obGdtX3ByX21lZCkgYCB8ICAgYHIgcGFzdGUoUEZOQV9obF9tZWRpYW5fZ20pIGAgICAgfCBgciAgcGFzdGUoUEZOQV9obGdzZF9wcl9tZWQpIGAgICAgICAgICAgIHwgYHIgcGFzdGUoUEZOQV9obF9nc2RfbWVkKWAgIHwgCnwgSEwgIFs5NSUgQ0ldICB8YHIgcGFzdGUwKCJbIixQRk5BX2hsZ21fcHJfbWVkXzk1Y2ksIl0iKWAgfCBgciBwYXN0ZTAoICJbIixQRk5BX2hsX21lZGlhbl9nbV85NWNpLCJdIilgfCBgciBwYXN0ZTAoIlsiLFBGTkFfaGxnc2RfcHJfbWVkXzk1Y2ksIl0iKWB8IGByIHBhc3RlMCggIlsiLFBGTkFfaGxfZ3NkX21lZF85NWNpLCAiXSIpYHwKfCBWb2x1bWUgb2YgZGlzdHJpYnV0aW9uICAgIHwgYHIgcGFzdGUoUEZOQV92ZF9nbV9wcl9tZWQpIGAgfCAgICBgciBwYXN0ZSggIFBGTkFfdmRfZ21fbWVkKSBgfCAgIGByICBwYXN0ZShQRk5BX3ZkX2dzZF9wcl9tZWQpYCAgfGByICBwYXN0ZShQRk5BX3ZkX2dzZF9tZWQpYCB8ICAKfCAkVl9EJCBbOTUlIENJXSAgICB8YHIgcGFzdGUwKCAiWyIsUEZOQV92ZF9nbV9wcl9tZWRfOTVjaSwiXSIpYHwgYHIgcGFzdGUwKCAiWyIsUEZOQV92ZF9nbV9tZWRfOTVjaSwiXSIpYHwgYHIgcGFzdGUwKCJbIixQRk5BX3ZkX2dzZF9wcl9tZWRfOTVjaSwgIl0iKWB8IGByIHBhc3RlMCggICJbIixQRk5BX3ZkX2dzZF9tZWRfOTVjaSwgIl0iKWB8IAp8IENsZWFyYW5jZSAgICB8IGByIHBhc3RlKFBGTkFfY2xfZ21fcHJfbWVkKSBgIHwgICAgYHIgcGFzdGUoICBQRk5BX2NsX2dtX21lZCkgYHwgICBgciAgcGFzdGUoKWAgIHxgciAgcGFzdGUoKWAgfCAgCnwgJENMJCBbOTUlIENJXSAgICB8YHIgcGFzdGUwKCAiWyIsUEZOQV9jbF9nbV9wcl9tZWRfOTVjaSwiXSIpYHwgYHIgcGFzdGUwKCAiWyIsUEZOQV9jbF9nbV9tZWRfOTVjaSwiXSIpYHwgYHIgcGFzdGUwKCJbIiwgIl0iKWB8IGByIHBhc3RlMCggICJbIiwgIl0iKWB8IAogCgoKCiMjIyBJbmRpdmlkdWFsIFBvc3RlcmlvciBlc3RpbWF0ZXMgCgp8IFBhcmFtZXRlciAgICAgICAgICAgICAgICAgICAgICB8ICBtZWRpYW4gR00gIFs5NSUgQ0ldIFtbOTglIENJXV0gfCBHTSBjYWxjdWxhdG9yIGlucHV0ICB8ICBHU0QgaW5kaXZpZHVhbCB8CnwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tLS0tLS0tLTp8Oi0tLS0tLS0tLS0tLS0tLS0tLS0tLTp8IAp8IEhhbGYtbGlmZSAoeWVhcnMpICAgICAgICAgICAgICB8IGByICBwYXN0ZShtZWRfaGxfaSwgIlsiLGNpX21lZF9obF9pLCJdIiwgIltbIixjaTk4X21lZF9obF9pLCJdXSIpIGAgfCBgciAgcGFzdGUoZ21faGxfaSkgYCB8IGByICBwYXN0ZShnc2RfaGxfaSkgYHwKfCBWb2x1bWUgb2YgZGlzdHJpYnV0aW9uICRWX0QkICAgfCBgciAgcGFzdGUobWVkX1ZkX2ksICJbIixjaV9tZWRfVmRfaSwiXSIsICJbWyIsY2k5OF9tZWRfVmRfaSwiXV0iKSBgIHwgYHIgIHBhc3RlKGdtX3ZkX2kpIGAgfCBgciAgcGFzdGUoZ3NkX3ZkX2kpIGB8IAoKCmBgYHtyIGVjaG89RkFMU0V9CmRldnRvb2xzOjpzZXNzaW9uX2luZm8oKQpgYGA=